Back to Parent

#include <SPI.h>
#include <MFRC522.h>

/*
 * Project GardeningStick
 * Description:
 * Author:
 * Date:
 */

 #define SS_PIN A2
 #define RST_PIN D0
 #define ID_LEN 4

 #define MOISTURE_IN A0 // pin for reading moisture values, must be analog
 #define MOISTURE_EN D1 // pin for activating the moisture sensor

//RFID globals
MFRC522 rfid(SS_PIN, RST_PIN);
MFRC522::MIFARE_Key key;
byte nuidPICC[ID_LEN] ;



/********************RFID helper functions**************************/
char arr_equal(void *arr1, void *arr2, unsigned len) {
  char *a1 = (char *)arr1 ;
  char *a2 = (char *)arr2 ;
  for (unsigned i =0 ; i < len; i++) {
    if(a1[i] != a2[i]) {
      return 0 ;
    }
  }
  return 1 ;
}

/**
 * Helper routine to dump a byte array as hex values to Serial.
 */
void printHex(byte *buffer, byte bufferSize) {
  for (byte i = 0; i < bufferSize; i++) {
    Serial.print(buffer[i] < 0x10 ? " 0" : " ");
    Serial.print(buffer[i], HEX);
  }
}

/**
 * Helper routine to dump a byte array as dec values to Serial.
 */
void printDec(byte *buffer, byte bufferSize) {
  for (byte i = 0; i < bufferSize; i++) {
    Serial.print(buffer[i] < 0x10 ? " 0" : " ");
    Serial.print(buffer[i], DEC);
  }
}

// refresh the nuid buffer
void resetNUID() {
  for(int i = 0; i < ID_LEN ; i++) {
    nuidPICC[i] = 0 ;
  }
}

/***************Helper functions for moisture sensor*************/
#define DRY (0)
#define WET (1)

int soil_state ;
//moisture sensor globals
int moisture_max = 4096 ; // assuming 12 bit ADC input
int moisture_threshold_lo = 200 ;
//int moisture_threshold_hi ;
// int lastMoisture ;

void printSoilState() {
  if(soil_state == DRY) {
    Serial.println(F("Soil is dry")) ;
    return ;
  }
  Serial.println(F("Soil is wet")) ;
}

// returns the moisture level from the sensors
int getMoistureLevel() {
  digitalWrite(MOISTURE_EN, HIGH) ;
  int wait_ms = 10 ;
  delay(wait_ms) ; //delay 10ms
  int moisture_level = analogRead(MOISTURE_IN) ;
  digitalWrite(MOISTURE_EN, LOW) ; // turn off moisture sensor
  return moisture_level ;
}

// returns 1 if curr_moisture is < low threshold specified
unsigned char needWater() {
  int curr_moisture = getMoistureLevel() ;
  return curr_moisture < moisture_threshold_lo ;
}


unsigned char justWatered() {
  int curr_moisture = getMoistureLevel() ;
  if((soil_state == DRY) && (curr_moisture > moisture_threshold_lo)) {
    soil_state = WET ;
    return 1 ;
  }
  return 0 ;
}

void updateSoilState() {
  if(needWater()) {
    soil_state = DRY ;
  }
  else {
    soil_state = WET ;
  }
  return ;
}

void setupMoistureSensor() {
  //setup moisture detector
  pinMode(MOISTURE_IN, INPUT) ;
  pinMode(MOISTURE_EN, OUTPUT) ;
  moisture_max = 880 ; // maximum moisture Analog input value
  delay(10) ;
  updateSoilState() ;
}


/**************Helper functions for sending to twiiter**************/

unsigned long time_of_last_read = 0 ; // can simply start with 0
unsigned long refresh_period = 1000 ;// in milliseconds

// returns 1 if refresh_period expired since last rfid read
unsigned char lastUserExpired() {
  unsigned long elapsed = millis() - time_of_last_read ;
  return elapsed > refresh_period ;
}

// increment social credit
void rewardUser(byte *uid) {
  Serial.print("Rewarding User: ") ;
  printHex(uid, ID_LEN) ;
  Particle.publish("plantWatered", "user1") ;
  Serial.println() ;
}

// post twitter request for water
void requestForWater() {
  Serial.println("Requesting for water") ;
  /* Uncomment the line below to tweet for water 
   * Care should be taken to run this functiion only sporadically to prevent
   * exceeding of twitter's API rate limit
   */
  // Particle.publish("plantDry", "dry") ;
}

// call when same user is detected
void handleSameUser(byte *old_uid) {
  Serial.println("Handling same user") ;
  time_of_last_read = millis() ;
  if(justWatered()) {
    rewardUser(old_uid) ;
  }
}

// call when new user is encountered
void handleNewUser(byte *new_uid) {
  Serial.println("Handling new user") ;
  time_of_last_read = millis() ;
  if(justWatered()) {
    rewardUser(new_uid) ;
  }
}

// resets variables regarding tracking user info and state
void resetUserInfo() {
  resetNUID() ;
  time_of_last_read = millis() ;
}

// returns 1 if uid is a user i,e if uid != [0,0,0,0]
char isUser(byte *uid) {
  for(int i =0; i < ID_LEN; i++) {
    if(uid[i] != 0) {
      return 1 ;
    }
  }
  return 0 ;
}


void setupRewardSystem() {
  resetUserInfo() ;
  // setup code for twitter webhooks
}


/****************Main loop and setup*****************************/
// setup() runs once, when the device is first turned on.
void setup() {
  Serial.begin(9600) ;
  Serial.println("Starting...") ;

  setupMoistureSensor() ;
  setupRewardSystem() ;

  // setup RFID device
  rfid.setSPIConfig() ;
  // SPI.begin() ;
  rfid.PCD_Init() ; // Init MFRC522
  for (char i=0; i < 6; i++) {
    key.keyByte[i] = 0xff ;
  }
  Serial.println(F("This code scans the MIFARE Classsic NUID."));
  Serial.print(F("Using the following key:"));
  printHex(key.keyByte, MFRC522::MF_KEY_SIZE);
}

void loop() {
  // Look for new cards
  if ( ! rfid.PICC_IsNewCardPresent()) {
    // Serial.println("Same Card Detected") ;
    if(!isUser(nuidPICC)) {
      return ;
    }
    else if(lastUserExpired()) { //isUser and user expired
        resetUserInfo() ;
    }
    else if(justWatered()) { //justWatered and isUser
      // to account for watering after the user has left vicinity
      rewardUser(nuidPICC) ;
    }
    return;
  }
  // Verify if the NUID has been read
  if ( ! rfid.PICC_ReadCardSerial()) {
    //Serial.println("Trying to read tag") ;
    return;
  }

  // Serial.print(F("PICC type: "));
  MFRC522::PICC_Type piccType = (MFRC522::PICC_Type)rfid.PICC_GetType(rfid.uid.sak);
  // Serial.println(rfid.PICC_GetTypeName(piccType));

  // Check is the PICC of Classic MIFARE type
  if (piccType != MFRC522::PICC_TYPE_MIFARE_MINI &&
    piccType != MFRC522::PICC_TYPE_MIFARE_1K &&
    piccType != MFRC522::PICC_TYPE_MIFARE_4K) {
    Serial.println(F("Your tag is not of type MIFARE Classic."));
    return;
  }

  // rfid encountered new user
  if(!arr_equal(rfid.uid.uidByte, nuidPICC, ID_LEN)) {
    Serial.println("New card detected") ;
    //store new uid
    for(byte i = 0; i < ID_LEN; i++) {
      nuidPICC[i] = rfid.uid.uidByte[i] ;
    }
    Serial.println(F("The NUID tag is:"));
    Serial.print(F("In hex: "));
    printHex(rfid.uid.uidByte, rfid.uid.size);
    Serial.println();
    //Serial.print(F("In dec: "));
    //printDec(rfid.uid.uidByte, rfid.uid.size);
    //Serial.println();
    handleNewUser(nuidPICC) ;
    printSoilState() ;
    Serial.println(getMoistureLevel());
  }
  else { // same user scanning card
    Serial.println(F("Card read previously."));
    handleSameUser(nuidPICC) ;
  }
  // Halt PICC
  rfid.PICC_HaltA();

  // Stop encryption on PCD
  rfid.PCD_StopCrypto1();

  updateSoilState() ; // checks and updates state of soil
  if(needWater()) {
    requestForWater() ;
  }
}
Click to Expand

Content Rating

Is this a good/useful/informative piece of content to include in the project? Have your say!

0