I'm trying to toggle the use of a stepper motor using a button and an RFID reader. Both work in isolation but when I try and use them both together it doesn't work. The stepper shudders and the RFID tags can't be read. I'm thinking I'll need to do something to make sure the RFID tags are programmed and read before going any further. Perhaps the condition below should be a while loop instead of an if statement or something like that.
Any suggestions welcome.
This code is the offending code:
/*
if (readRFID() == true) {
Serial.println("Reading tag");
myTags[tagsCount] = strdup(tagID.c_str()); // Sets the master tag into position 0 in the array
Serial.println(F("Master Tag is Set!"));
tagsCount++;
}
printNormalModeMessage();
*/
Here's the readRFID function and how its used in the setup function:
bool readRFID(long _timeout=timeout, bool useTimeout=false){
/* readRFID will continuously check the RFID reader for the presence of
* a tag from and will attempt to get tag IDs. Updates global value
* tagID via getTagID function.
* Parameters:
* _timeout - [optional] the length of time before functio gives up
* default value = global timout value
* useTimeout - [optional] boolean to enforce timout period or wait
* indefinately. Default value = false.
* Returns:
* true - successfully reads tag ID
* false - unsuccessful in reading the tag ID
*/
bool successRead = false;
unsigned long startTime = millis();
unsigned long currentTime = startTime;
// S'U'+S'T'
// T = (currentTime-startTime) > timeout
// T' = (currentTime-startTime) < timeout
while (((successRead==false)&&(useTimeout==false)) || ((successRead==false)&&((currentTime - startTime) < _timeout))) {
if (isTagPresent() == true){ successRead = getTagID(); }
currentTime = millis();
}
return successRead;
}
void setup() {
Serial.begin(9600);
SPI.begin(); // Start SPI bus
rfidReader.PCD_Init(); // Start MFRC522 object
while (!Serial); // Do nothing if no serial port is opened
// Obviously this is an over simplified sketch
// Master tags would be save in flash storage and
// retrieved here. OR a special PIN entered to set
// Master Tag.
// But for the sake of simplicity, the sketch will
// obtain a new master tag when restarted.
// Prints the initial message
Serial.println(F("-No Master Tag!-"));
Serial.println(F(" SCAN NOW"));
// readRFID will wait until a master card is scanned
/*
if (readRFID() == true) {
Serial.println("Reading tag");
myTags[tagsCount] = strdup(tagID.c_str()); // Sets the master tag into position 0 in the array
Serial.println(F("Master Tag is Set!"));
tagsCount++;
}
printNormalModeMessage();
*/
// Set the maximum speed in steps per second:
stepper.setMaxSpeed(1000);
pinMode(buttonPin, INPUT);
pinMode(RED, OUTPUT);
pinMode(GREEN, OUTPUT);
digitalWrite(RED, HIGH);
digitalWrite(GREEN, LOW);
}
/*
Debounce
Each time the input pin goes from LOW to HIGH (e.g. because of a push-button
press), the output pin is toggled from LOW to HIGH or HIGH to LOW. There's a
minimum delay between toggles to debounce the circuit (i.e. to ignore noise).
The circuit:
- LED attached from pin 13 to ground through 220 ohm resistor
- pushbutton attached from pin 2 to +5V
- 10 kilohm resistor attached from pin 2 to ground
- Note: On most Arduino boards, there is already an LED on the board connected
to pin 13, so you don't need any extra components for this example.
created 21 Nov 2006
by David A. Mellis
modified 30 Aug 2011
by Limor Fried
modified 28 Dec 2012
by Mike Walters
modified 30 Aug 2016
by Arturo Guadalupi
This example code is in the public domain.
https://www.arduino.cc/en/Tutorial/BuiltInExamples/Debounce
*/
#include <SPI.h>
#include <MFRC522.h>
// Include the AccelStepper library:
#include <AccelStepper.h>
// Other hardware pins
const byte rstPin = 39; // Reset pin
const byte ssPin = 53; // Slave Select pin
// Define stepper motor connections and motor interface type. Motor interface type must be set to 1 when using a driver:
#define dirPin 2
#define stepPin 3
#define motorInterfaceType 1
// constants won't change. They're used here to set pin numbers:
const int buttonPin = 45; // the number of the pushbutton pin
const int ledPin = 27; // the number of the LED pin
// Define Pins
#define BLUE 25
#define GREEN 23
#define RED 27
// Variables will change:
int ledState = HIGH; // the current state of the output pin
int buttonState; // the current reading from the input pin
int lastButtonState = LOW; // the previous reading from the input pin
// the following variables are unsigned longs because the time, measured in
// milliseconds, will quickly become a bigger number than can be stored in an int.
unsigned long lastDebounceTime = 0; // the last time the output pin was toggled
unsigned long debounceDelay = 50; // the debounce time; increase if the output flickers
const long timeout = 30000; // Timeout in ms
// Create a new instance of the AccelStepper class:
AccelStepper stepper = AccelStepper(motorInterfaceType, stepPin, dirPin);
// Instantiate MFRC522 object class
MFRC522 rfidReader(ssPin, rstPin);
char* myTags[100] = {};
int tagsCount = 0;
String tagID = "";
bool readRFID(long _timeout=timeout, bool useTimeout=false){
/* readRFID will continuously check the RFID reader for the presence of
* a tag from and will attempt to get tag IDs. Updates global value
* tagID via getTagID function.
* Parameters:
* _timeout - [optional] the length of time before functio gives up
* default value = global timout value
* useTimeout - [optional] boolean to enforce timout period or wait
* indefinately. Default value = false.
* Returns:
* true - successfully reads tag ID
* false - unsuccessful in reading the tag ID
*/
bool successRead = false;
unsigned long startTime = millis();
unsigned long currentTime = startTime;
// S'U'+S'T'
// T = (currentTime-startTime) > timeout
// T' = (currentTime-startTime) < timeout
while (((successRead==false)&&(useTimeout==false)) || ((successRead==false)&&((currentTime - startTime) < _timeout))) {
if (isTagPresent() == true){ successRead = getTagID(); }
currentTime = millis();
}
return successRead;
}
void setup() {
Serial.begin(9600);
SPI.begin(); // Start SPI bus
rfidReader.PCD_Init(); // Start MFRC522 object
while (!Serial); // Do nothing if no serial port is opened
// Obviously this is an over simplified sketch
// Master tags would be save in flash storage and
// retrieved here. OR a special PIN entered to set
// Master Tag.
// But for the sake of simplicity, the sketch will
// obtain a new master tag when restarted.
// Prints the initial message
Serial.println(F("-No Master Tag!-"));
Serial.println(F(" SCAN NOW"));
// readRFID will wait until a master card is scanned
/*
if (readRFID() == true) {
Serial.println("Reading tag");
myTags[tagsCount] = strdup(tagID.c_str()); // Sets the master tag into position 0 in the array
Serial.println(F("Master Tag is Set!"));
tagsCount++;
}
printNormalModeMessage();
*/
// Set the maximum speed in steps per second:
stepper.setMaxSpeed(1000);
pinMode(buttonPin, INPUT);
//pinMode(ledPin, OUTPUT);
pinMode(RED, OUTPUT);
pinMode(GREEN, OUTPUT);
//pinMode(BLUE, OUTPUT);
digitalWrite(RED, HIGH);
digitalWrite(GREEN, LOW);
//digitalWrite(BLUE, LOW);
}
void loop() {
// read the state of the switch into a local variable:
int reading = digitalRead(buttonPin);
// check to see if you just pressed the button
// (i.e. the input went from LOW to HIGH), and you've waited long enough
// since the last press to ignore any noise:
// If the switch changed, due to noise or pressing:
if (reading != lastButtonState) {
// reset the debouncing timer
lastDebounceTime = millis();
}
if ((millis() - lastDebounceTime) > debounceDelay) {
// whatever the reading is at, it's been there for longer than the debounce
// delay, so take it as the actual current state:
// if the button state has changed:
if (reading != buttonState) {
buttonState = reading;
// only toggle the LED if the new button state is HIGH
if (buttonState == LOW) {
ledState = !ledState;
toggleLock(ledState);
digitalWrite(RED, !digitalRead(RED)); // toggle the output
digitalWrite(GREEN, !digitalRead(GREEN)); // toggle the output
}
}
}
// set the LED:
//digitalWrite(ledPin, ledState);
// save the reading. Next time through the loop, it'll be the lastButtonState:
lastButtonState = reading;
/*
if (isTagPresent()==true){
getTagID();
checkTagID();
} else {
//delay(10);
//return
}
*/
}
void toggleLock(int ledState){
if(ledState == HIGH){
// Reset the position to 0:
stepper.setCurrentPosition(0);
// Run the motor backwards at 600 steps/second until the motor reaches -200 steps (1 revolution):
while(stepper.currentPosition() != -100)
{
stepper.setSpeed(-600);
stepper.runSpeed();
}
} else {
// Reset the position to 0:
stepper.setCurrentPosition(0);
// Run the motor forward at 400 steps/second until the motor reaches 600 steps (3 revolutions):
while(stepper.currentPosition() != 100)
{
stepper.setSpeed(400);
stepper.runSpeed();
}
}
//return 1;
}
/* ***********************************************************
* Functions *
* ********************************************************* */
bool isTagPresent(){
/* isTagPresent uses the MFRC522 methods to determine if
* a tag is present or the read card serial is enabled.
* Parameters: (none)
* Returns:
* true - if tag detected or read card serial is true
* false - no tag detected or no read card serial true
*/
bool returnValue = true;
// NOT a new PICC_IsNewCardPresent in RFID reader
//OR
// NOT a PICC_ReadCardSerial active in Serial
if ( !rfidReader.PICC_IsNewCardPresent() || !rfidReader.PICC_ReadCardSerial() ) {
returnValue = false;
}
return returnValue;
}
byte checkMyTags(String tagID){
/* checkMyTags function loops through the array of myTags
* Parameters:
* tagID - a string to look for
* Returns:
* tagIndex - index in the array of myTags
* default 0
*/
byte tagIndex = 0;
//Serial.println("checkMyTags Started");
// Zero is reserved for master tag
for (int i = 1; i < 100; i++) {
if (tagID == myTags[i]) { tagIndex = i; }
}
//Serial.println("checkMyTags ended");
return tagIndex;
}
void checkTagID(){
/* checkTagID check the tag ID for authorized tag ID values
* if Master tag found switch to program mode
* Parameters: (none)
* Returns: (none)
*/
// Checks for Master tag
if (tagID == myTags[0]) {
// Switch to program mode
Serial.println(F(" Program mode:"));
Serial.println(F(" Add/Remove Tag"));
// Now with timeout
// readRFID will skip if timeout exceeded
// if (readRFID(timeout,true)==true) {
if (readRFID()==true) {
//Check for authorized tag
byte tagIndex = checkMyTags(tagID);
if (tagIndex!=0){
//Remove existing tag
myTags[tagIndex] = '\0';
Serial.println(F(" Tag Removed!"));
} else {
//Not existing, add tag
myTags[tagsCount] = strdup(tagID.c_str());
Serial.println(F(" Tag Added!"));
tagsCount++;
}
} else {
Serial.println(F(" timeout"));
}
} else {
//Check for authorized tag
byte tagIndex = checkMyTags(tagID);
if (tagIndex!=0){
//Authorized tag
Serial.println(F(" Access Granted!"));
//unlock();
} else {
//Not authorized tag
//lock();
Serial.println(F(" Access Denied!"));
Serial.println(F(" New UID & Contents:"));
rfidReader.PICC_DumpToSerial(&(rfidReader.uid));
}
}
printNormalModeMessage();
}
bool getTagID() {
/* getTagID retrieves the tag ID. Modifies global variable tagID
*
* Parameters: (none)
* Returns: true
*/
tagID = "";
Serial.print(F(" UID tag: "));
for (byte i = 0; i < rfidReader.uid.size; i++){
// The MIFARE PICCs that we use have 4 byte UID
Serial.print(rfidReader.uid.uidByte[i] < 0x10 ? " 0" : " ");
Serial.print(rfidReader.uid.uidByte[i], HEX);
// Adds the bytes in a single String variable
tagID.concat(String(rfidReader.uid.uidByte[i] < 0x10 ? " 0" : " "));
tagID.concat(String(rfidReader.uid.uidByte[i], HEX));
}
Serial.println();
Serial.println();
tagID.toUpperCase();
rfidReader.PICC_HaltA(); // Stop reading
return true;
}
void printNormalModeMessage() {
/* printNormalModeMessage sends the standard greeting
* to the serial monitor.
* Parameters: (none)
* Returns: (none)
*/
// delay(1500);
Serial.println();
Serial.println(F("-Access Control-"));
Serial.println(F(" Scan Your Tag!"));
}
I'm trying to build a very simple lock. What I want to do is toggle the state of a stepper motor. Press a button and the motor turns X amount of steps in one direction and present an RFID tag and turn the motor X amount of steps in the opposite direction.
I've got the switch working independently of the RFID, they both work but I can't get them to work together. The stepper motor shudders when switched on, no idea why. Doesn't appear to be a circuit issue.
This is my code:
I've hit a brick wall so any suggestions are welcome.
Why is there a switch in the stepper motor circuit? Your description tells us the power supply for the stepper motor is either too low voltage or too low current or both.
Your two or more topics on the same or similar subject have been merged.
Please do not duplicate your questions as doing so wastes the time and effort of the volunteers trying to help you as they are then answering the same thing in different places.
Please create one topic only for your question and choose the forum category carefully. If you have multiple questions about the same project then please ask your questions in the one topic as the answers to one question provide useful context for the others, and also you won’t have to keep explaining your project repeatedly.
Repeated duplicate posting could result in a temporary or permanent ban from the forum.
Could you take a few moments to Learn How To Use The Forum
It will help you get the best out of the forum in the future.
I'll need to draw out a diagram. I'm convinced its a code issue though. The motor shouldn't even run when the circuit is switched on, its shuddering so it seems that in the loop/setup function the code is confused about what it should be doing.
Is there anything obvious you can see in the code before I start drawing out a diagram?
Yeah, that's what I started with. I had code for operating the motor and then I added the code for the RFID, they both work independently its just trying to get both working at the same time which is the issue and why I don't think its the circuit. Its like both the switch and RFID have to wait for interaction and that's causing the confusion.
Since you already have tested code for the devices, on you next post, please explain in detail exactly what you want the new combined program to do. Apparently you have not figured this out, yet. Once you know EXACTLY what the combined program should do, you will be able to write the new program.
What I'm trying to achieve is a simple door lock. The RFID for locking/unlocking from the outside and the switch on the inside for the same thing on the inside. I'm trying to get this to work by toggling the state of the the motors.
The only way I can think of to get this to work as I want is to use two Arduinos, one for the RFID and the other for the switch. I would then maintain a record of the state of the the motors to an SD card. Surely it must be possible to do with one Arduino though.