string comparing issue  - Page 1
Forum section: electronics / general

author: King123
author_rank: Contributor
timestamp: August 23, 2022, 06:49:38 pm
content: My Arduino mega 2560 with RFID-em18 reader but I am stuck in my program. I want to give access to only five cards , if any other card is scanned except these , it should not get accessI want to gives access to following cards just for testingCode:FF0064F9D492FF0064F9D492FF0064F6D41CFF0064F9D482FF0064F6D47CThis is my sketch that check and compare only one tag. It's working fineCode:char tag[] ="FF0064F9D492"; // Replace with your own Tag IDchar input; // A variable to store the Tag ID being presentedint count = 0; // A counter variable to navigate through the input[] character arrayboolean flag = 0; // A variable to store the Tag match statusvoid setup(){Serial.begin(9600); // Initialise Serial Communication with the Serial MonitorSerial1.begin(9600);}void loop(){if(Serial1.available())// Check if there is incoming data in the RFID Reader Serial Buffer.{count = 0; // Reset the counter to zero/* Keep reading Byte by Byte from the Buffer till the RFID Reader Buffer is emptyor till 12 Bytes (the ID size of our Tag) is read */while(Serial1.available() && count < 12){input = Serial1.read(); // Read 1 Byte of data and store it in the input[] variablecount++; // increment counterdelay(5);}/* When the counter reaches 12 (the size of the ID) we stop and compare each valueof the input[] to the corresponding stored value */if(count == 12) //{count =0; // reset counter varibale to 0flag = 1;/* Iterate through each value and compare till either the 12 values areall matching or till the first mistmatch occurs */while(count<12 && flag !=0){if(input==tag)flag = 1; // everytime the values match, we set the flag variable to 1elseflag= 0;/* if the ID values don't match, set flag variable to 0 andstop comparing by exiting the while loop */count++; // increment i}}if(flag == 1) // If flag variable is 1, then it means the tags match{Serial.println("Access Allowed!");}else{Serial.println("Access Denied"); // Incorrect Tag Message}/* Fill the input variable array with a fixed value 'F' to overwriteall values getting it empty for the next read cycle */for(count=0; count<12; count++){input= 'F';}count = 0; // Reset counter variable}}I am struggling to check multiple tags in loopCode:char tag[] = {"FF0064F9D492", "FF0064F9D492", "FF0064F6D41C", "FF0064F9D482", "FF0064F6D47C"};I am struggling following part of program How to compare each tags in codeCode:while(Serial1.available() && count < 12){input = Serial1.read(); // Read 1 Byte of data and store it in the input[] variablecount++; // increment counterdelay(5);}/* When the counter reaches 12 (the size of the ID) we stop and compare each valueof the input[] to the corresponding stored value */if(count == 12) //{count =0; // reset counter varibale to 0flag = 1;/* Iterate through each value and compare till either the 12 values areall matching or till the first mistmatch occurs */while(count<12 && flag !=0){if(input==tag)flag = 1; // everytime the values match, we set the flag variable to 1elseflag= 0;/* if the ID values don't match, set flag variable to 0 andstop comparing by exiting the while loop */count++; // increment i}}

author: nctnico
author_rank: Super Contributor
timestamp: August 23, 2022, 07:00:14 pm
content: Why aren't you using strcmp() or strncmp() from the standard C library (string.h) to compare? You'll need an extra loop to go through the list with tags. The tags array has 2 dimensions! Create a flow chart of your program first.A good option would be to test your code on a PC first. Step through it with a debugger to verify the program does what you intend it to do.

author: SiliconWizard
author_rank: Super Contributor
timestamp: August 23, 2022, 07:31:11 pm
content: Quote from: nctnico on August 23, 2022, 07:00:14 pmProbably because they don't know about them? From the little I've seen - I may have missed something though - the OP is trying to compare strings with the '==' operator. Well, uh. Nope.They need to learn C. Not sure the whole Arduino thing really pushes people to properly learn, I dunno.

author: wek
author_rank: Frequent Contributor
timestamp: August 23, 2022, 07:49:55 pm
content: Forstrcmp()to work, the string has to be ASCIIZ i.e. zero terminated. And for that, one extra char has to be allocatedCode:char input[12 + 1]; // A variable to store the Tag ID being presented, plus one place for the NULL char: input = '\0';Also, #include <string.h> has to be added at the beginning.JW

author: langwadt
author_rank: Super Contributor
timestamp: August 23, 2022, 08:57:33 pm
content: https://cplusplus.com/reference/cstring/strncmp/

author: cv007
author_rank: Frequent Contributor
timestamp: August 23, 2022, 08:58:35 pm
content: You can use the C++ range based for loop which would simplify-https://godbolt.org/z/vdzjhbKzfand if you want to print the input string, will want to 0 terminate input (and then can also use strcmp since 0 terminated)-https://godbolt.org/z/Yv8vPv8nP

author: SiliconWizard
author_rank: Super Contributor
timestamp: August 24, 2022, 12:19:18 am
content: Quote from: cv007 on August 23, 2022, 08:58:35 pm- Problem with using C++ features is, why we know that Arduino is using C++ under the hood, we never know exactly how much of it is actually allowed/supported. For instance, using std C++ strings (not C) is probably not recommended. It's rather unclear what subset of C++ is allowed and the official description on Arduino's website doesn't help much.- As to comparing strings here, rather than fiddle with adding a terminal zero, the OP can just use memcmp() instead of strcmp() on 12 bytes. It will probably even be slightly faster.

author: King123
author_rank: Contributor
timestamp: August 24, 2022, 12:32:35 am
content: Quote from: cv007 on August 23, 2022, 08:58:35 pmI ran code and check tag but doesn't print anythingCode:#include "Arduino.h"const char* cards_allow[]{"FF0064F9D492","FF0064F9D492","FF0064F6D41C","FF0064F9D482","FF0064F6D47C"};void setup() {// put your setup code here, to run once:Serial1.begin(9600);}void loop(){static const auto CARD_SIZE{ 12 };static uint8_t count;static char input;while( Serial1.available() and (count < CARD_SIZE) ) input[count++] = Serial1.read();if( count < CARD_SIZE ) return;bool found = false;for( auto card : cards_allow ){if( strncmp(card, input, CARD_SIZE) == 0 ){found = true;break;}}Serial.println( found ? "Access Allowed!" : "Access Denied" );count = 0;if( found ){ /* do something */ }Serial.println("Allowed");}

author: fourfathom
author_rank: Super Contributor
timestamp: August 24, 2022, 12:58:43 am
content: Echo the characters as they are received to see what you are getting. You might need to flush the receive buffer before trying to read in the ID number.

author: King123
author_rank: Contributor
timestamp: August 24, 2022, 01:17:52 am
content: Quote from: fourfathom on August 24, 2022, 12:58:43 amWhat happens in following line ? Does there need to add delayCode:while( Serial1.available() and (count < CARD_SIZE) ) input[count++] = Serial1.read();if( count < CARD_SIZE ) return;

author: brucehoult
author_rank: Super Contributor
timestamp: August 24, 2022, 01:52:58 am
content: Quote from: SiliconWizard on August 23, 2022, 07:31:11 pmThey are using == to compare CHARACTERS, which is fine.QuoteEveryone needs to start somewhere. Attracting beginners and enabling them to do cool things is a strength of Arduino, not a fault.

author: cv007
author_rank: Frequent Contributor
timestamp: August 24, 2022, 02:10:58 am
content: QuoteThe C++ compiler will certainly tell you when you use something not supported. A range based for loop has been around for a long time (C++11?), and can certainly be used here. There is also nothing preventing standard library replacements, since you have the same underlying language the standard library writer does. There is no standard library strings for avr (arduino does their own version), but its not needed in this case. The array of const char pointers is nothing special, and a range base for loop can easily iterate through those pointers.The C++ language is always available when using a C++ compiler, regardless of whether you use a standard library (if available). I use C++ all the time, no C++ standard library. If you use arduino, no reason to leave all the C++ features on the shelf. You are 'allowed' to use anything the compiler version allows (gcc 7.3.0 = c++17), and arduino has no say in what you 'may' use.You can simulate this code for a pc, where the online compiler will produce output you can read-https://godbolt.org/z/MsE31q5b9The arduino Serial class is simulated, so you have to provide a (read) string to it when creating the Serial1 instance. Change the string to see different results. Instead of strcmp, strcasecmp was also used so case can also be different.Another version where you can set the 'read' string at runtime to test various numbers-https://godbolt.org/z/3Kozxbba3(the print output is in the right panel)QuoteThat code was using Serial in a few places where Serial1 should have been used, which was a mistake.

author: SiliconWizard
author_rank: Super Contributor
timestamp: August 24, 2022, 03:56:26 am
content: Quote from: brucehoult on August 24, 2022, 01:52:58 amThat's messier than this: they are comparing a character with a string (which led me to believe they were trying to just compare strings, but that wasn't even it), since 'tag' is an array of strings from what they gave us?So anyway - just use memcmp() and call it a day, since all strings in 'tag' have the same length.