I'm creating a device reads a RFID tag, creates a lighting effect, and then does an action like unlocking a door with a solenoid value (as an example). This project goes beyond my normal understanding of coding... I have several books that I reference but most of them must be old because the topic of RFID is only mentioned briefly in one and so I'm having some trouble understanding what each element does.
I started by making three LED programs using the adafruit neopixel library to show different states; passive while waiting for a tag to come in range, active when a correct tag is used; and fail-to-read when a tag is wrong. Separately i started learning about RFID tags, which are fairly new to me in concept.
so I have a fair understanding right now of writing simple addressable LED programs, and a fuzzy at best understanding of using RFID tech. I figured I could use a simple code with if statements to satisfy my needs but I couldn't get that to work. Here is the first attempt i threw together using the "playful tech" tutorial "Escape Room Object Placement Puzzle using Arduino/RFID" his tutorial, i feel, is the best at giving a play by play of what the code is doing :
#include <Adafruit_NeoPixel.h>
#include <FastLED.h>
#define PIN 6
#define NUMPIXELS 60
#define TRACE_LENGTH 6
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_RGB + NEO_KHZ800);
int delayval = 1000 / 20;
CRGB leds[NUMPIXELS];
// DEFINES
// Provides debugging information over serial connection if defined
#define DEBUG
// LIBRARIES
// Standard SPI library comes bundled with the Arduino IDE
#include <SPI.h>
// Download and install from https://github.com/miguelbalboa/rfid
#include <MFRC522.h>
// CONSTANTS
// The number of RFID readers
const byte numReaders = 1;
// Each reader has a unique Slave Select pin
const byte ssPins[] = {10};
// They'll share the same reset pin
const byte resetPin = 9;
// This pin will be driven LOW to release a lock when puzzle is solved
const byte lockPin = A0;
// The sequence of NFC tag IDs required to solve the puzzle
const String correctIDs[] = {"b7d19134"};
// GLOBALS
// Initialise an array of MFRC522 instances representing each reader
MFRC522 mfrc522[numReaders];
// The tag IDs currently detected by each reader
String currentIDs[numReaders];
/**
* Initialisation
*/
void setup() {
pixels.begin ();
pixels.show ();
pixels.setBrightness(255);
FastLED.addLeds<WS2812B, PIN, RGB>(leds, NUMPIXELS);
#ifdef DEBUG
// Initialise serial communications channel with the PC
Serial.begin(9600);
Serial.println(F("Serial communication started"));
#endif
// Set the lock pin as output and secure the lock
pinMode(lockPin, OUTPUT);
digitalWrite(lockPin, HIGH);
// Initialise the SPI bus
SPI.begin();
for (uint8_t i=0; i<numReaders; i++) {
mfrc522[i].PCD_Init(ssPins[i], resetPin);
// Set the gain to max - not sure this makes any difference...
// mfrc522[i].PCD_SetAntennaGain(MFRC522::PCD_RxGain::RxGain_max);
#ifdef DEBUG
// Dump some debug information to the serial monitor
Serial.print(F("Reader #"));
Serial.print(i);
Serial.print(F(" initialised on pin "));
Serial.print(String(ssPins[i]));
Serial.print(F(". Antenna strength: "));
Serial.print(mfrc522[i].PCD_GetAntennaGain());
Serial.print(F(". Version : "));
mfrc522[i].PCD_DumpVersionToSerial();
#endif
// Slight delay before activating next reader
delay(100);
}
#ifdef DEBUG
Serial.println(F("--- END SETUP ---"));
#endif
}
/**
* Main loop
*/
void loop() {
// Assume that the puzzle has been solved
boolean puzzleSolved = true;
// Assume that the tags have not changed since last reading
boolean changedValue = false;
// Loop through each reader
for (uint8_t i=0; i<numReaders; i++) {
// Initialise the sensor
mfrc522[i].PCD_Init();
// String to hold the ID detected by each sensor
String readRFID = "";
// If the sensor detects a tag and is able to read it
if(mfrc522[i].PICC_IsNewCardPresent() && mfrc522[i].PICC_ReadCardSerial()) {
// Extract the ID from the tag
readRFID = dump_byte_array(mfrc522[i].uid.uidByte, mfrc522[i].uid.size);
}
// If the current reading is different from the last known reading
if(readRFID != currentIDs[i]){
// Set the flag to show that the puzzle state has changed
changedValue = true;
// Update the stored value for this sensor
currentIDs[i] = readRFID;
}
// If the reading fails to match the correct ID for this sensor
if(currentIDs[i] != correctIDs[i]) {
// The puzzle has not been solved
puzzleSolved = false;
////addition
while(puzzleSolved = false){
for(int i = 0; i <= NUMPIXELS; i++)
{
leds[i] = CHSV (200,200,100);
FastLED.show();
delay(4);
leds[i] = CHSV (250,100,2);
FastLED.show();
delay(40);
}
for(int i = NUMPIXELS ; i >= 0; i--){
leds[i] = CRGB (0,0,0);
FastLED.show();
delay(30);
}
}
}
// Halt PICC
mfrc522[i].PICC_HaltA();
// Stop encryption on PCD
mfrc522[i].PCD_StopCrypto1();
}
#ifdef DEBUG
// If the changedValue flag has been set, at least one sensor has changed
if(changedValue){
// Dump to serial the current state of all sensors
for (uint8_t i=0; i<numReaders; i++) {
Serial.print(F("Reader #"));
Serial.print(String(i));
Serial.print(F(" on Pin #"));
Serial.print(String((ssPins[i])));
Serial.print(F(" detected tag: "));
Serial.println(currentIDs[i]);
}
Serial.println(F("---"));
}
#endif
// If the puzzleSolved flag is set, all sensors detected the correct ID
if(puzzleSolved){
onSolve();
}
// Add a short delay before next polling sensors
//delay(100);
} else{
//Tracing led effect
int i = 0;
while(true) {
pixels.setPixelColor(i, pixels.Color(0,0,162));
pixels.setPixelColor(i - TRACE_LENGTH, pixels.Color(0,0,0));
pixels.show();
delay(delayval);
i = ( i + 1) % (NUMPIXELS + TRACE_LENGTH);
}
}
/**
* Called when correct puzzle solution has been entered
*/
void onSolve(){
#ifdef DEBUG
// Print debugging message
Serial.println(F("Puzzle Solved!"));
#endif
//Pulsing led effect
theaterChase(pixels.Color(100, 100, 127), 50); // White, half brightness
}
void theaterChase(uint32_t color, int wait) {
for(int a=0; a<10; a++) { // Repeat 10 times...
for(int b=0; b<3; b++) { // 'b' counts from 0 to 2...
pixels.clear(); // Set all pixels in RAM to 0 (off)
// 'c' counts up from 'b' to end of pixels in steps of 3...
for(int c=b; c<pixels.numPixels(); c += 3) {
pixels.setPixelColor(c, color); // Set pixel 'c' to value 'color'
}
pixels.show(); // Update pixels with new contents
delay(wait); // Pause for a moment
}
}
while(true) {
delay(1000);
}
}
/**
* Helper function to return a string ID from byte array
*/
String dump_byte_array(byte *buffer, byte bufferSize) {
String read_rfid = "";
for (byte i=0; i<bufferSize; i++) {
read_rfid = read_rfid + String(buffer[i], HEX);
}
return read_rfid;
}
I figured I could just put the LED loops in there to make it simple but I this only made the LED trace play on loop and when the proper tag was read, the serial monitor read puzzle solved with no change in the led strip.
for the second attempt I did something more complicated by using multiple arduinos. when the master detected the tab, it sent a signal to either arduino telling either to start the program if a pin was written HIGH.
My last attempt was to still have separate arduinos but use mofsets to either turn power to two separate LED strips HIGH. the problem with this is that when they shut off, the led strips freeze and stay that way until I flip the power switch.
I'm certain its much easier than Im making it and I finally just have to ask for some advice.
This is what Im after:
I want my LED trace effect to happen while it is waiting to scan a card
when a card is found I want it to be seen as either the right tag or wrong tag.
if its the wrong tag I want to run a different program for so many seconds and then return to being passive
if it is the right tag, I want it to run yet another program for so many seconds, make an action, then return to being passive.
please forgive me if this is formatted incorrectly I've been sitting here searching through the forum guidelines and i'm having trouble finding how I format the code to read better...