RFID card credit system

Hello,

I have recently been working on a code that will read and write data to and from a Mifare Classic 1k card. I created a code from scratch using the IDE program. It receives a 3 digit number from a 4x4 keypad, reads the initial value on the card, adds it to the keypad value, then writes it to the card, overwriting the previous number. I also added some serial print outs in the code to help me diagnose the problem, and it seems as though it gets the number, but has trouble writing it to the card. I am using a RC-522 shield on an Arduino Uno. (I know this is unrelated to the problem, but I am also using a 16x2 LCD with a I2c backpack to display other information) Here is the code:

#include <SPI.h>
#include <Wire.h>
#include <Keypad.h>
#include <MFRC522.h>
#include <MFRC522Extended.h>
#include <LiquidCrystal_I2C.h>

#define ss_pin 10
#define rst_pin 9

int character = 0;
char Str[16] = {'A', 'm', 'o', 'u', 'n', 't', ':', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '};

MFRC522 rfid(ss_pin, rst_pin);

MFRC522::MIFARE_Key key;

LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

bool addMode = false;

const byte rows = 4;
const byte cols = 4;

char keys[rows][cols] = {
  {'1','2','3','A'},
  {'4','5','6','B'},
  {'7','8','9','C'},
  {'*','0','#','D'}
  };

byte rowPins[rows] = {8,7,6,5};
byte colPins[cols] = {4,3,2,A1};

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, rows, cols);

void setup() {
  
  Serial.begin(9600);
  SPI.begin();
  rfid.PCD_Init();

  for (byte i = 0; i < 6; i++) {
    key.keyByte[i] = 0xFF;
  }
  
  //LCD Init
  lcd.begin(16,2);
  lcd.setCursor(0,0);
  lcd.clear();
  lcd.display();

  lcd.clear();
  lcd.print("Insert Card");
  lcd.setCursor(0,1);
  lcd.print("and Type Amount");
  lcd.display();
}

void loop() {
    // put your main code here, to run repeatedly:

    char keyp = keypad.getKey();
    
    if (keyp){
      if(character == 0)
      {
        Serial.println(keyp);
        Str[9] = keyp;
        lcd.clear();
        lcd.setCursor(0,0);
        lcd.print(" -Type Amount-");
        lcd.setCursor(0,1);
        lcd.print(Str);
      }
       if(character == 1)
      {
        Serial.println(keyp);
        Str[10] = keyp;
        lcd.clear();
        lcd.setCursor(0,0);
        lcd.print(" -Type Amount-");
        lcd.setCursor(0,1);
        lcd.print(Str);
      }
      if(character == 2)
      {
        Serial.println(keyp);
        Str[11] = keyp;
        lcd.clear();
        lcd.setCursor(0,0);
        lcd.print(" -Type Amount-");
        lcd.setCursor(0,1);
        lcd.print(Str);

      }
      character=character+1;
    }

    byte amt1 = ((Str[9] - 48) * 100);
    byte amt2 = ((Str[10] - 48) * 10);
    byte amt3 = (Str[11] - 48);
    
    if (character == 3)
      {
        if ( ! rfid.PICC_IsNewCardPresent())
          return;

        if ( ! rfid.PICC_ReadCardSerial())
          return;
        
        byte sector = 1;
        byte blockAddr = 4;
        byte trailerblock = 7;

        byte dataBlock[16];

        byte buffer[18];
        byte size = sizeof(buffer);
        
        byte amt = (amt1 + amt2 + amt3);
        
        MFRC522::StatusCode status;

        Serial.println(F("Authenticating using key A...."));
        status = (MFRC522::StatusCode) rfid.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, trailerblock, &key, &(rfid.uid));
        if (status != MFRC522::STATUS_OK) {
          Serial.print(F("PCD_Authenticate() failed: "));
          Serial.println(rfid.GetStatusCodeName(status));
          return;
        }

        Serial.print("Current Balence: ");
        Serial.println(rfid.MIFARE_Read(blockAddr, buffer, &size));

        byte tamt = amt + (rfid.MIFARE_Read(blockAddr, buffer, &size));

        Serial.print("New Balence should be: ");
        Serial.println(tamt);
        
        tamt = buffer[15];
        
        dataBlock[15] = tamt;
        status = (MFRC522::StatusCode) rfid.MIFARE_Write(blockAddr, dataBlock, 16);
        if (status != MFRC522::STATUS_OK) {
          Serial.print(F("MIFARE_Write() failed: "));
          Serial.println(rfid.GetStatusCodeName(status));
        }

        Serial.print(F("New Balence Written: "));
        Serial.println(rfid.MIFARE_Read(blockAddr, buffer, &size));
        if (status != MFRC522::STATUS_OK) {
          Serial.print(F("MIFARE_Read() failed: "));
          Serial.println(rfid.GetStatusCodeName(status));
          return;
        }

        Serial.println(F("Current data in sector:"));
        rfid.PICC_DumpMifareClassicSectorToSerial(&(rfid.uid), &key, sector);
        Serial.println();
      }

}

Any ideas? Did I do anything stupid? Any suggestions are highly appreciated. Thanks for your help!

-Samuel Johnson

byte tamt = amt + (rfid.MIFARE_Read(blockAddr, buffer, &size));

I don't know the library that you're using. But given that you pass a buffer to this read function, I seriously doubt that it just returns whatever number it finds in there as an int that you can add in a math statement.

You need to read that block and then parse out the number and add that. Parsing a number from a string is a well covered topic.

Thank you for your reply, Delta_G!

I did some research and came up with this:

for (uint8_t i = 0; i < 16; i++)
          {
            if (buffer[i] != 32)
            {
              Serial.write(buffer[i]);           
            }
            byte tamt = amt + (buffer[i]);

I am new to parsing, as you can probably tell, so please bear with me.
Would this work? Thank you for your support,

Samuel Johnson

On second thought,

It might be easier to just convert the hexadecimal into decimal form to make it legible. Would this work?? If the rfid stores data in hexadecimal, converting it into decimal form would allow me to print that string at the integer. Just throwing out ideas. Any thoughts??

-Samuel Johnson

The RFID card can only store binary data. If that binary data is an ascii representation of some numerical value is up to you and your code. But it can only ever be binary on the card. I would just store the value directly that way.

would allow me to print that string at the integer

You're going to have to explain what you mean here by printing at an integer.

Your probably right, however Arduino seems to be representing it in hexadecimal, as shown in the attachment. All I'm wondering is if I have to translate the data from hexadecimal to decimal to be read, or do I need to do something else?

You're going to have to explain what you mean here by printing at an integer.

What I meant was "as" an integer. Doing this would allow the data to be read as an integer instead of hexadecimal.

When I run the code, it says that the data written is "0." I don't know why, maybe it's something to do with your parsing, or it has to do with a conversion. I just want it to write and read the data; how to do so, other than what I did, I don't know. I spent hours looking online for an example and couldn't find one, so as a last resort I came here. I am completely in the dark.

Thank you for your help,

Samuel Johnson

Doing this would allow the data to be read as an integer instead of hexadecimal.

There's no such thing as a decimal number or a hexadecimal numbers. Those are ways of WRITING numbers. That only matters if they are being stored in ascii. If you're writing the actual numbers then decimal or hex are meaningless. They're being written as binary.

So the question is, are the numbers on the card stored in ascii? What is actually written on the card?

I honestly don't know what is being written on the card, as I didn't change anything. I only use what the library has (what that writes it in, ascii or binary, I don't know) but it's probably binary. I would like to know why my code isn't doing what it's supposed to do. Is it writing it, but I just can't read it because I need to parse it? Or is it having trouble writing it? If it's just parsing, could you please tell me if the example I came up with on reply #2 would work, or am I missing how parsing works?? I am very curious why it's not working, and if I could get an answer that would be totally great.

I am using the library by Miguel Balboa on GitHub: GitHub - miguelbalboa/rfid: Arduino RFID Library for MFRC522

Thanks again,

Samuel Johnson