cat food reader.

i didnt really know how to title this so i appologize for any confusion, but here is what im trying to accomplish.

im building out a cat food dish that will measure how much my cats are each eating (among other stats).

im using an RFID reader and have RFID tags in each of their collars to distingush who is who.

EXPECTED RESULTS

cat A approaches the bowl. the rfid reader triggers and takes a reading of how much food is in the bowl. cat eats some food. then when the cat leaves, the program then compares how much food is the bowl now to how much was in the bowl when the cat first started eating. then sends the difference via MQTT to my server. (using an ESP32 for this)

CURRENT RESULTS

rfid triggers and takes the reading, but as long as the cat is eating the RFID tag is still being detected so it is consantly updating the food value for how much food is present. so by the time the cat leaves the bowl the last updated food value is the same. it compares the before and after values and returns 0 food eaten.

basically im scratching my head as so to how can i meaure the scales value once as soon as the RFID reader detects a cat, then dont take any more readings untill the cat walks away?

im working through the code and have been trying all sorts of stuff, so its not exactly pretty right now, but here is what im working with thus far.

#include <PubSubClient.h>
#include <PN5180.h>
#include <PN5180ISO15693.h>
#include <WiFi.h>
#include <HX711_ADC.h>
#include <EEPROM.h>


const int HX711_dout = 4; //mcu > HX711 dout pin
const int HX711_sck = 2; //mcu > HX711 sck pin
const char* ssid     = "PriFree";
const char* password = "91950864";

const uint8_t peaches[8] = {0x50,0x1A,0xE3,0xD7,0x50,0x01,0x04,0xE0};
const uint8_t lilly[8] = {0x70,0x11,0xE3,0xD7,0x50,0x01,0x04,0xE0};

 



HX711_ADC LoadCell(HX711_dout, HX711_sck);
const int calVal_eepromAdress = 0;
unsigned long t = 0;

//MQTT Setup Start
#define mqtt_server "192.168.0.109"
WiFiClient espClient;
PubSubClient client(espClient);
int pf_weight;
int p_weight;
int food_weight;
int food_start;
int food_eaten;
float eating, eating_time, eating_start;

float runMillis = millis();
int addTime = 1000;
float newTime = 0 ;
uint32_t loopCnt = 0;
bool errorFlag = true;


//used for MQTT
#define  mqttP_weight "CS/p_weight"  //weight of item
#define  mqttPf_weight"CS/pf_weight" //weight of item2
//#define  p_time "CS/timer"      //long this lasted
//#define  p_uses "CS/count++"    //count rfid triggers in 24hr cycle

#define  mqttL_weight "CS/scale_w"  //weight of item
#define  mqttLf_weight "CS/scale_f" //weight of item2
//#define  l_time "CS/timer"      //long this lasted
//#define  l_uses "CS/count++"

//MQTT Setup end


#define PN5180_NSS  21 
#define PN5180_BUSY 5  
#define PN5180_RST  22

PN5180ISO15693 nfc15693(PN5180_NSS, PN5180_BUSY, PN5180_RST);
PN5180ISO15693 nfc(PN5180_NSS, PN5180_BUSY, PN5180_RST);




void setup() {
  Serial.begin(115200);
  nfc.begin();
  nfc.reset();
  nfc.setupRF();
  LoadCell.begin();
  delay(10);

    // We start by connecting to a WiFi network

/* 
 *  
 *  WiFi.mode(WIFI_STA);
 WiFi.begin(ssid, password);
 while (WiFi.status() != WL_CONNECTED){
  delay(500);
  Serial.print("");  }

Serial.print("SSID: ");
Serial.println(ssid);
Serial.print("LAN IP: ");
Serial.println(WiFi.localIP());

client.setServer(mqtt_server, 1883);
client.connect("CatStats");

*/


int value = 0;

 float calibrationValue; // calibration value (see example file "Calibration.ino")
 calibrationValue = 1895.25; // uncomment this if you want to set the calibration value in the sketch
#if defined(ESP8266)|| defined(ESP32)
  //EEPROM.begin(512); // uncomment this if you use ESP8266/ESP32 and want to fetch the calibration value from eeprom
#endif
  //EEPROM.get(calVal_eepromAdress, calibrationValue); // uncomment this if you want to fetch the calibration value from eeprom

  unsigned long stabilizingtime = 5000; // preciscion right after power-up can be improved by adding a few seconds of stabilizing time
  boolean _tare = true; //set this to false if you don't want tare to be performed in the next step
  LoadCell.start(stabilizingtime, _tare);
  if (LoadCell.getTareTimeoutFlag()) {
    Serial.println("Timeout, check MCU>HX711 wiring and pin designations");
    while (1);
  }
  else {
    LoadCell.setCalFactor(calibrationValue); // set calibration value (float)
    Serial.println("Startup is complete");
  }
}

void loop() {
  scale1();
  rfid();
  noCard();
 }






void scale1(){

  static boolean newDataReady = 0;
  const int serialPrintInterval = 5; //increase value to slow down serial print activity

  // check for new data/start next conversion:
  if (LoadCell.update()) newDataReady = true;
      

  // get smoothed value from the dataset:
  if (newDataReady) {
    if (millis() > t + serialPrintInterval) {
       food_weight = LoadCell.getData();
      
      newDataReady = 0;
      t = millis();
      
    }
  }

  // receive command from serial terminal, send 't' to initiate tare operation:
  if (Serial.available() > 0) {
    char inByte = Serial.read();
    if (inByte == 't') LoadCell.tareNoDelay();
  }

  // check if last tare operation is complete:
  if (LoadCell.getTareStatus() == true) {
    Serial.println("Tare complete");
  }

}

void rfid(){


uint8_t uid[8];

  ISO15693ErrorCode rc = nfc15693.getInventory(uid);
  if (rc == ISO15693_EC_OK) {

    if(memcmp(uid, peaches, 8) == 0){
      eating_start = millis();
      food_start = food_weight;
      
    Serial.print ("Food:");
    Serial.println(food_weight);
    Serial.print("Time:");
    Serial.println (eating_start);
    
    }
    
     
     if(errorFlag == true && millis() > eating_start){
        eating_time = eating - eating_start;
        food_eaten = food_start - food_weight;

       Serial.print("Time:");
       Serial.println(eating_time);
       Serial.print("Food_eaten:");
       Serial.println(food_eaten);
       
       //eating_time = 0;
       errorFlag = false;
       //food_eaten = 0;
       
       
      }
    
    
    if(memcmp(uid, lilly, 8) == 0){
    Serial.println ("LILLY");
   }
    
}
}
 



void noCard() {
  if (errorFlag) {
    uint32_t irqStatus = nfc.getIRQStatus();
    //showIRQStatus(irqStatus);

    if (0 == (RX_SOF_DET_IRQ_STAT & irqStatus)) { // no card detected
      Serial.println(F("*** No card detected!"));
      errorFlag = true;
      delay(1000);
    }

    nfc.reset();
    nfc.setupRF();

    //errorFlag = false;
  }

  
 /*uint8_t uid[8];
  ISO15693ErrorCode rc = nfc.getInventory(uid);
  if (ISO15693_EC_OK != rc) {
    errorFlag = true;
    return;
  }*/
}


void showIRQStatus(uint32_t irqStatus) {
  Serial.print(F("IRQ-Status 0x"));
  Serial.print(irqStatus, HEX);
  Serial.print(": [ ");
  if (irqStatus & (1<< 0)) Serial.print(F("RQ "));
  if (irqStatus & (1<< 1)) Serial.print(F("TX "));
  if (irqStatus & (1<< 2)) Serial.print(F("IDLE "));
  if (irqStatus & (1<< 3)) Serial.print(F("MODE_DETECTED "));
  if (irqStatus & (1<< 4)) Serial.print(F("CARD_ACTIVATED "));
  if (irqStatus & (1<< 5)) Serial.print(F("STATE_CHANGE "));
  if (irqStatus & (1<< 6)) Serial.print(F("RFOFF_DET "));
  if (irqStatus & (1<< 7)) Serial.print(F("RFON_DET "));
  if (irqStatus & (1<< 8)) Serial.print(F("TX_RFOFF "));
  if (irqStatus & (1<< 9)) Serial.print(F("TX_RFON "));
  if (irqStatus & (1<<10)) Serial.print(F("RF_ACTIVE_ERROR "));
  if (irqStatus & (1<<11)) Serial.print(F("TIMER0 "));
  if (irqStatus & (1<<12)) Serial.print(F("TIMER1 "));
  if (irqStatus & (1<<13)) Serial.print(F("TIMER2 "));
  if (irqStatus & (1<<14)) Serial.print(F("RX_SOF_DET "));
  if (irqStatus & (1<<15)) Serial.print(F("RX_SC_DET "));
  if (irqStatus & (1<<16)) Serial.print(F("TEMPSENS_ERROR "));
  if (irqStatus & (1<<17)) Serial.print(F("GENERAL_ERROR "));
  if (irqStatus & (1<<18)) Serial.print(F("HV_ERROR "));
  if (irqStatus & (1<<19)) Serial.print(F("LPCD "));
  Serial.println("]");
}

The first time that you read the tag and the amount of food, set a flag. Have an if statement that allows reading the food only if the flag is not set. You would still attempt to read the flag while the cat is eating so that you can detect when the cat leaves.

When the cat is finished and the tag goes away, clear the flag so that the next time that the tag is detected the code will read the food and set the flag.

groundFungus:
The first time that you read the tag and the amount of food, set a flag. Have an if statement that allows reading the food only if the flag is not set. You would still attempt to read the flag while the cat is eating so that you can detect when the cat leaves.

When the cat is finished and the tag goes away, clear the flag so that the next time that the tag is detected the code will read the food and set the flag.

boom! that did the trick! i guess that is a pretty obvious solution, but i just wasnt seeing it. thanks for advice i appreciate it!

This trick is called "state change detection". There's an example in the IDE related to input signals showing how it works.

Not a practical project surely.
Where we live, the toads get in to any cat food left unattended and sometimes even sleep in the bowl after a gut full.

bluejets:
Not a practical project surely.
Where we live, the toads get in to any cat food left unattended and sometimes even sleep in the bowl after a gut full.

You have toads wandering around in your house?

evanmars:
You have toads wandering around in your house?

beats rats, I suppose, and a tossup on mice . . .

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.