Bluetooth(HC-06) and RFID RC522(using MFRC522)

Hi. I used RFID module, AVR (atmega128), Bluetooth module hc-06.
I connected RFID module and Bluetooth module to AVR by wire. After connecting Bluetooth and mit app inventor, I want to make the app inventor count if I tag the card in RFID module.
I made a test code to let me know that when I tagged a card in the RFID reader, the app tagged the card. However, no matter how much I change the AVR code and modify the mit app inventory code, nothing changes on the app's screen when I tag the card on the RFID module.
The test code I made is as below.
And hex on the card are " 03 55 11 D8 ". By Chatgpt, in App Inventor the card UID is represented in decimal for each byte. Therefore, converting 0x03, 0x55, 0x11, 0xD8 to decimal as 3, 85, 17, 216 is the correct setting.
Also just in case, I'll post the code for AVR studio 4 (atmega128) in number 3.

Please help me which part is the problem! I need your help~~

  1. MIT app inventor code


2.Result (.apk)



Using listpicker, I succeeded in connecting the application with the Bluetooth module. But even if I tag the card, it doesn't change except for label2. And label2(Received Raw Data: ) keeps changing into numbers before tagging the card!!

  1. AVR code (similar with Arduio)
    (1) RFID module - atmega128 using portB
    (2) bluetooth mocule(HC-06) - atmega128 using UART1
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <string.h>

#define F_CPU 16000000UL

// Define RFID card UID
const uint8_t UID_CARD_1[4] = {0x03, 0x55, 0x11, 0xD8};  // UID of the card to be used

// Function declarations
void init();
void uart1_init(long baud);
void uart1_transmit(unsigned char data);
void uart1_send_string(const char *str);
void spi_init();
uint8_t spi_transmit(uint8_t data);
void mfrc522_init();
void mfrc522_reset();
void mfrc522_write(uint8_t reg, uint8_t data);
uint8_t mfrc522_read(uint8_t reg);
uint8_t mfrc522_request(uint8_t req_mode, uint8_t *tag_type);
uint8_t mfrc522_get_card_serial(uint8_t *serial_out);
uint8_t mfrc522_to_card(uint8_t cmd, uint8_t *send_data, uint8_t send_data_len, uint8_t *back_data, uint32_t *back_data_len);

void send_card_uid(const uint8_t *uid);

int main(void) {
    uint8_t byte;
    uint8_t cardUID[4];

    // Initialization
    init();
    uart1_init(9600);       // Initialize UART1 for Bluetooth module
    spi_init();             // Initialize SPI
    mfrc522_init();         // Initialize RFID reader

    while (1) {
        // Bluetooth connection test message
        uart1_send_string("Waiting for card...\n");
        
        // Detect RFID card
        byte = mfrc522_request(0x52, cardUID); // PICC_REQALL command
        if (byte == 1) { // CARD_FOUND
            byte = mfrc522_get_card_serial(cardUID);
            if (byte == 1) { // CARD_FOUND
                // Check if the card UID matches UID_CARD_1
                if (memcmp(cardUID, UID_CARD_1, 4) == 0) {
                    uart1_send_string("Card 1 tagged\n");  // Debug message
                    send_card_uid(UID_CARD_1);  // Send Card 1 UID
                }
                _delay_ms(1000);  // Prevent duplicate tag
            }
        }
    }
}

void init() {
    DDRB = 0xFF;  // Set Port B as output (for RFID SPI connection)
}

void uart1_init(long baud) {
    unsigned int ubrr = (F_CPU / 16 / baud - 1);
    UBRR1H = (unsigned char)(ubrr >> 8);
    UBRR1L = (unsigned char)ubrr;
    UCSR1B = (1 << RXEN1) | (1 << TXEN1); // Enable RX, TX
    UCSR1C = (1 << UCSZ11) | (1 << UCSZ10); // Set data to 8 bits
}

void uart1_transmit(unsigned char data) {
    while (!(UCSR1A & (1 << UDRE1)));
    UDR1 = data;
}

void uart1_send_string(const char *str) {
    while (*str) {
        uart1_transmit(*str++);
    }
}

void send_card_uid(const uint8_t *uid) {
    for (int i = 0; i < 4; i++) {
        uart1_transmit(uid[i]);
    }
}

void spi_init() {
    DDRB |= (1 << PB2) | (1 << PB1) | (1 << PB0); // Set MOSI, SCK, SS as output
    SPCR = (1 << SPE) | (1 << MSTR) | (1 << SPR0); // Enable SPI, set as Master mode, set clock prescaler to 16
}

uint8_t spi_transmit(uint8_t data) {
    SPDR = data;
    while (!(SPSR & (1 << SPIF)));
    return SPDR;
}

void mfrc522_init() {
    mfrc522_reset();
    mfrc522_write(0x2A, 0x8D);
    mfrc522_write(0x2B, 0x3E);
    mfrc522_write(0x2C, 30);
    mfrc522_write(0x2D, 0);
    mfrc522_write(0x15, 0x40);
    mfrc522_write(0x11, 0x3D);
}

void mfrc522_reset() {
    mfrc522_write(0x01, 0x0F); // SoftReset command to CommandReg
}

void mfrc522_write(uint8_t reg, uint8_t data) {
    PORTB &= ~(1 << PB0); // SS Low
    spi_transmit((reg << 1) & 0x7E);
    spi_transmit(data);
    PORTB |= (1 << PB0);  // SS High
}

uint8_t mfrc522_read(uint8_t reg) {
    uint8_t data;
    PORTB &= ~(1 << PB0); // SS Low
    spi_transmit(((reg << 1) & 0x7E) | 0x80);
    data = spi_transmit(0x00);
    PORTB |= (1 << PB0);  // SS High
    return data;
}

uint8_t mfrc522_request(uint8_t req_mode, uint8_t *tag_type) {
    uint8_t status;
    mfrc522_write(0x0D, 0x07); // Set BitFramingReg
    tag_type[0] = req_mode;
    status = mfrc522_to_card(0x0C, tag_type, 1, tag_type, NULL); // Transceive_CMD
    return status;
}

uint8_t mfrc522_to_card(uint8_t cmd, uint8_t *send_data, uint8_t send_data_len, uint8_t *back_data, uint32_t *back_data_len) {
    uint8_t status = 0;
    uint8_t irqEn = 0x00;
    uint8_t waitIRq = 0x00;
    uint8_t lastBits;
    uint8_t n;
    uint32_t i;

    switch (cmd) {
    case 0x0E:      // MFAuthent_CMD authentication card
        irqEn = 0x12;
        waitIRq = 0x10;
        break;
    case 0x0C:      // Transceive_CMD transmit FIFO data
        irqEn = 0x77;
        waitIRq = 0x30;
        break;
    default:
        break;
    }

    mfrc522_write(0x02, irqEn | 0x80);   // Interrupt request
    mfrc522_write(0x04, 0x80);           // Clear CommIrqReg
    mfrc522_write(0x0A, 0x80);           // Initialize FIFO

    mfrc522_write(0x01, 0x00);           // Set command to Idle state

    // Write data to FIFO
    for (i = 0; i < send_data_len; i++) {
        mfrc522_write(0x09, send_data[i]);
    }

    // Execute command
    mfrc522_write(0x01, cmd);

    // Wait to receive data
    i = 2000;
    do {
        n = mfrc522_read(0x04);
        i--;
    } while ((i != 0) && !(n & 0x01) && !(n & waitIRq));

    if (i != 0) {
        if (!(mfrc522_read(0x06) & 0x1B)) {
            status = 1;
            if (n & irqEn & 0x01) {
                status = 0;
            }

            if (cmd == 0x0C) {
                n = mfrc522_read(0x0A);
                lastBits = mfrc522_read(0x0C) & 0x07;
                if (lastBits) {
                    *back_data_len = (n - 1) * 8 + lastBits;
                } else {
                    *back_data_len = n * 8;
                }

                if (n == 0) {
                    n = 1;
                }
                if (n > 16) {
                    n = 16;
                }

                // Read received data from FIFO
                for (i = 0; i < n; i++) {
                    back_data[i] = mfrc522_read(0x09);
                }
            }

For byte values > 127, you need to Receive Unsigned Bytes.

I fixed it with UNSIGNED because I think you're talking about this part, but it still doesn't recognize the card tag on app inventory.

Looking at your sketch, I see your 4 bytes of UID floating down a river of UART1 text garbage.(commentary about status.)

If you are going to send text, send ONLY text.

That makes room for using delimiters like \n (decimal 10) between each message and the next.

You look skilled in coding, so convert those 4 bytes to an 8 byte ASCII text string wrapped in \n, to make the AI2 code simple.

Here's standard AI2 BT text reception advice:
Be sure to use println() at the end of each message to send from the sending device, to signal end of message.

Only use print() in the middle of a message.

Be sure not to println() in the middle of a message, or you will break it into two short messages and mess up the item count after you split the message in AI2.

Do not rely on timing for this, which is unreliable.

In the AI2 Designer, set the Delimiter attribute of the BlueTooth Client component to 10 to recognize the End of Line character.
BlueToothClient1_Properties
Also, return data is not immediately available after sending a request,
you have to start a Clock Timer repeating and watch for its arrival in the Clock Timer event. The repeat rate of the Clock Timer should be faster than the transmission rate in the sending device, to not flood the AI2 buffers.

In your Clock Timer, you should check

  Is the BlueTooth Client still Connected?
  Is Bytes Available > 0?
     IF Bytes Available > 0 THEN
       set message var  to BT.ReceiveText(-1) 

This takes advantage of a special case in the ReceiveText block:

ReceiveText(numberOfBytes)
Receive text from the connected Bluetooth device. If numberOfBytes is less than 0, read until a delimiter byte value is received.

If you are sending multiple data values per message separated by | or comma, have your message split into a local or global variable for inspection before trying to select list items from it. Test if (length of list(split list result) >= expected list length) before doing any select list item operations, to avoid taking a long walk on a short pier. This bulletproofing is necessary in case your sending device sneaks in some commentary messages with the data values.

Some people send temperature and humidity in separate messages with distinctive prefixes like "t:" (for temperature) and "h:" (for humidity).
(That's YAML format.)

The AI2 Charts component can recognize these and graph them. See Bluetooth Client Polling Rate - #12 by ABG

To receive YAML format messages, test if the incoming message contains ':' . If true, split it at ':' into a list variable, and find the prefix in item 1 and the value in item 2.

...