Jump to content
D69

Odd results coming from a char* array

Recommended Posts

Hi all

I'm currently working with Eelcor's excellent port of the RC522 Mifare library.

All is well on the hardware side and most of the code is functioning fine, there's just one section where I'm trying to use a switch/case based on the results of an array lookup (as for loop).

The switch works comparing an integer but the value I want is in a char* array which is the only way I can get the array working with the data I want.

The funny thing occurs when I try to get a variable to take on the int value of the array. The number always comes out as a negative but can also change, I think based on the amount of code but I'm not sure.

I'm positive I'm just being dense and it's something simple but I've gone over it several times and can't figure it out.

Any help appreciated

 

Cheers

Dean

/*
	Example file for communicating with the NFRC522. The program prints the card data.
	Created by Eelco Rouw - Originally adapted by Grant Gibson. 
*/

// Pinout
// SDA  - 2.2
// SCK  - 1.5
// Mosi - 1.7
// Miso - 1.6
// IRQ  - NC
// GND  - GND
// RST  - 1.3
// VCC  - VCC

#include <Mfrc522.h>

// the sensor communicates using SPI, so include the library:
#include <SPI.h>

int chipSelectPin = 10;
int NRSTDP = 5;
int ledpin1 = 13;
int ledpin2 = 12;
int ledpin3 = 11;
int cardint = 5;

Mfrc522 Mfrc522(chipSelectPin,NRSTDP);
unsigned char serNum[5];
int secLevel;
String secLevel2;
unsigned char sectorKey[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
unsigned char readData[16];

void setup() 
{                
	Serial.begin(9600);                       // RFID reader SOUT pin connected to Serial RX pin at 2400bps 
	// Start the SPI library:
	SPI.begin();
	// Initialize the Card Reader
	digitalWrite(chipSelectPin, LOW);
	pinMode(RED_LED, OUTPUT);
        pinMode(ledpin1, OUTPUT);
        pinMode(ledpin2, OUTPUT);
        pinMode(ledpin3, OUTPUT);
        digitalWrite(ledpin1, LOW);
        digitalWrite(ledpin2, LOW);
        digitalWrite(ledpin3, LOW);
	Mfrc522.Init();  
}

void loop()
{
	unsigned char i,tmp;
	unsigned char status;
	unsigned char str[MAX_LEN];
	unsigned char RC_size;
	unsigned char blockAddr;
        String mycardno;
        char* myarray[3][5]={  //Array of tags and related names, tag numbers copied from serial console after 1st run
          {"205928944228","1251291514471","7748944415","157172894468","611918944247"},
          {"Dad","Mum","Baby","Dog","Cat"},
          {"5","4","3","2","1"}
          };
  	
	status = Mfrc522.Request(PICC_REQIDL, str);	
	if (status == MI_OK)
	{
		Serial.println("Card detected");
		Serial.print(str[0],BIN);
		Serial.print(" , ");
		Serial.print(str[1],BIN);
		Serial.println(" ");
	}

	status = Mfrc522.Anticoll(str);
	memcpy(serNum, str, 5);
	if (status == MI_OK)
	{
		Serial.println("The card's number is  : ");
		Serial.print(serNum[0], DEC);
		Serial.print(" , ");
		Serial.print(serNum[1], DEC);
		Serial.print(" , ");
		Serial.print(serNum[2], DEC);
		Serial.print(" , ");
		Serial.print(serNum[3], DEC);
		Serial.print(" , ");
		Serial.print(serNum[4], DEC);
		Serial.println(" ");
                mycardno = String(serNum[0]) += String(serNum[1]) += String(serNum[2]) += String(serNum[3]) += String(serNum[4]); // Appends the content of the serNum array to give a unique card no
                Serial.println(mycardno);
                Mfrc522.SelectTag(serNum);
                status = Mfrc522.Auth(PICC_AUTHENT1A,1,sectorKey,serNum);
                if (status == MI_OK)
                {
                  Serial.println("Authenticated...\r\n");
                } else
                {
                  Serial.println("Error authenticating...\r\n");
                }
                
                status = Mfrc522.ReadBlock(1, readData);
                if (status == MI_OK)
                {
                  for(i=0; i<16; i++)
                  {                  
                    Serial.write(readData[i]);
                    delay(10);
                  }                  
                } else {
                  Serial.println("Error reading.");
                }
                int i;
                for(i = 0; i < 5; i = i + 1)
                {
                  if (mycardno == myarray[0][i])
                  {
                  Serial.print("Hello ");
                  Serial.println(myarray[1][i]);        // Should Print out name matching tag
                  secLevel = int(myarray[2][i]);        // Tried setting this to the int of the unsigned char
                  secLevel2 = String(myarray[2][i]);    // Setting the string version, works better
                  Serial.print("Security level: ");
                  Serial.println(myarray[2][i]);        // Returns correctly
                  Serial.println(secLevel);             // Returns random number based on current amount of code
                  Serial.println(secLevel2);            // Returns correctly
                }
                /*else {
                  Serial.println("Bugger Off");
                }*/
                }
                {
                  switch (secLevel) {
                    case -9844:
                    digitalWrite(ledpin1, HIGH);
                    digitalWrite(ledpin2, LOW);
                    digitalWrite(ledpin3, LOW);
                    break;
                    case -9842:
                    digitalWrite(ledpin1, LOW);
                    digitalWrite(ledpin2, HIGH);
                    digitalWrite(ledpin3, LOW);
                    break;
                    case -9840:
                    digitalWrite(ledpin1, LOW);
                    digitalWrite(ledpin2, LOW);
                    digitalWrite(ledpin3, HIGH);
                    break;
                    case -9838:
                    digitalWrite(ledpin1, HIGH);
                    digitalWrite(ledpin2, LOW);
                    digitalWrite(ledpin3, HIGH);
                    break;
                    case -9836:
                    digitalWrite(ledpin1, HIGH);
                    digitalWrite(ledpin2, HIGH);
                    digitalWrite(ledpin3, LOW);
                    break;
                  }
                }
  
		delay(1000);
                Mfrc522.Init();	
	}
	//Serial.println(" ");
	Mfrc522.Halt();	                        
}

Share this post


Link to post
Share on other sites

Do you try to get the integer values of these strings?

"5","4","3","2","1"

 

If so, the function you're looking for is atoi (ascii to integer).

secLevel = atoi(myArray[2]);

 

However, as long as we're talking about a single digit, you can also use

secLevel = myarray[2][i][0]

Note that [0] accesses the first character of the string stored at [2].

 

Subtract 0x30 (or '0') if you want to have an integer from 0-9, but the switch statement can handle character too ('0' is a character, "0" is a string).

Share this post


Link to post
Share on other sites

Your problem arises because my array[2] is the pointer to the string, not the string itself. Consequently your code seclevel=myarray[2] assigns the pointer value to sec level, not the data. That's why you get a seemingly random value depending on code size. myarray[2][0] will return the first char of the string pointed to by my array[2]. You could also dereference the pointer by using *(myarray[2]).

Share this post


Link to post
Share on other sites

Your problem arises because my array[2] is the pointer to the string, not the string itself. Consequently your code seclevel=myarray[2] assigns the pointer value to sec level, not the data. That's why you get a seemingly random value depending on code size. myarray[2][0] will return the first char of the string pointed to by my array[2]. You could also dereference the pointer by using *(myarray[2]).

Hi Graham

Is that because I used char*? I'm not sure why the array would only work as char*, maybe because of the mixed type of values?

Share this post


Link to post
Share on other sites

@@D69 - the problem you were encountering is fundamental to the way C handles arrays and strings. Firstly, as I'm sure you're aware a string is merely a null-terminated array of characters.  So the string "abc" is represented in memory as a group of characters, 'a', 'b', 'c' and '\0'. When you declare your array your array as char * myArray[3][5], you are creating an array of pointers to char arrays, so myArray[2][0] will return the pointer to the string "5", not the actual character 5. To get the character '5' you need to dereference the pointer, ie *(myArray[2][0]).

 

Personally, for ease of readability, rather than a multi-dimensioned array, I'd probably do something along the lines of:

typedef struct 
{
  char CardNo[13]; //1 larger than the maximum size so as to have room for the \0
  char Name[5];
  char SecurityLevel;
} tSecInfo;

tSecInfo myArray[5]={{"205928944228","Dad",5},{"1291251914471","Mum",4}, ... };

...
//then access the various parts with things like...

Serial.Println(myArray[i].Name);
seclevel=myArray[i].SecurityLevel;

etc.

Share this post


Link to post
Share on other sites

You're using the wrong design of your data type. You don't have an array of arrays of characters; you have an array of structures where each structure contains a serial number, a name and a sequence id (?).

Try replacing your data type as needed. Whenever you need to cast (force a type onto another type), you need to consider you're using the wrong design of your data.

Usually my answers are more complete, but I'm not capable of that right now.

Share this post


Link to post
Share on other sites

Hi Graham

After a bit of pondering your code really makes sense, just looking at rewriting mine to incorporate it now, should save a few lines and tidy it all up a bit.

I've not used typedef before but it actually seems quite logical, I'm assuming the order of variables declared should match the order they're listed in the array.

Thanks very much for the assistance, this forum seems to have one of the best user bases I've seen in a while!

Share this post


Link to post
Share on other sites

Hi RoadRunner

Your answer is complete enough for me! I figured I'd come across problems trying to fudge an array of strings and chars but I'm not competent enough yet to know what else to do :D

I double-posted for some reason and graham has suggested using another method that should hopefully improve  using typedef struct instead.

 

Thanks for the reply, any guidance is always appreciated.

Share this post


Link to post
Share on other sites

http://www.aliexpress.com/store/product/Free-shipping-RFID-module-Kits-RC522-RFID-SPI-Write-Read-for-uno-2560/320981_968016332.html

 

Hi !

 

 Please take a look at the above RFID card. I am getting a status of 2 after the Request. I think I am not doing some connection incorrectly.  :(..  I needed to finish this tonight but I am stuck.. I have tried connections based upon the pin connections above but does not seem to be working..  The NSS and the RST pins are the ones I am not sure I am connecting correctly.

 

Thanks !!!!!

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×