#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!
You must login before you can post a comment. .