Need help with C please

22 May 2010 . Edited: 22 May 2010

Hi:

I have been struggling with converting a program that runs on my Arduino over to the mbed.  I believe I am very close, but I'm not quite there.

I have a couple of questions from the output that I have copied below.  It looks like the code is working (finally) in that I can read tags, however, I am getting the same tag id no matter which tag I read.  I will display three output files below as they appear on Tera Term.  I also would like to understand why I am getting 7 Readable: 1 messages when I only expect to see one at the beginning of the output.

After the three output files, I have posted the code with the author's notes as the code is from the book Practical Arduino.  I have changed some of the code at the beginning of it as the mbed has a fully available serial port which the Arduino does not for this particular code as it's serial port is connecting to the PC.

I am using a low frequency Seeedstudio RDM630 reader module which is functionally the same as the ID-12.

NOTE for ease of transfer I have retained the Arduino format of

 

setup()
loop()

so my mbed code is

main()
  while(1)
    {
    setup();
    loop();
    }

 

I would really appreciate some notes on what is wrong with my C code.

Thanks

Tim

Output 1

edited to remove a note about my code being here as I was unable to copy it in until I closed the compiler, reopened the program and copied it again.

sorry I had to edit it again.  My first two output files were from the same tag.

Output 2 (second tag)

Readable: 1
bytesRead: 0
Tag READ: 33
tempByte: 3
bytesRead: 2
Tag READ: 42
tempByte: B
bytesRead: 4
Tag READ: 30
tempByte: 0
bytesRead: 6
Tag READ: 30
tempByte: 0
bytesRead: 8
Tag READ: 33
tempByte: 3
bytesRead: A
Tag READ: 34
tempByte: 4
Tag Value: 10007F90
Checksum: 0
--passed--Readable: 1
Readable: 1
Readable: 1
Readable: 1
Readable: 1
Readable: 1
Readable: 1

Output 3 (3rd tag)

 

 

Readable: 1
bytesRead: 0
Tag READ: 32
tempByte: 2
bytesRead: 2
Tag READ: 41
tempByte: A
bytesRead: 4
Tag READ: 30
tempByte: 0
bytesRead: 6
Tag READ: 30
tempByte: 0
bytesRead: 8
Tag READ: 35
tempByte: 5
bytesRead: A
Tag READ: 45
tempByte: E
Tag Value: 10007F90
Checksum: 0
--passed--Readable: 1
Readable: 1
Readable: 1
Readable: 1
Readable: 1
Readable: 1
Readable: 1

edited to add program file - not sure why it wouldn't go before but I think it was a full serial buffer.

 

//**************************************************************************************
//* RFID Routines
//**************************************************************************************
//* Read RFID Tag
//**************************************************************************************

//**************************************************************************************
//* This code is from the book Practical Arduino by Jonathon Oxer and Hugh Blemings    *
//* Other than as noted, I have reproduced it as written and with the authors          *
//* comments and explanations                                                          *
//* It absolutely works as written in the Arduino. I need help converting to "C"       *
//**************************************************************************************
//* The letters after the // are for me to track brackets eg //a-> open //a<- close
void loop()
     {//a->
     pc.baud(9600);
     RFID.baud(9600);
     int val       = 0;    // this should hold the character read from the reader
     int checksum  = 0;    // this is checked against a calculated checksum
     int bytesRead = 0;    // counter if number of bytes read (2 characters per)
     int tempByte  = 0;    // storage for character retreived
     int tagBytes[6];      // or 12 characters. 5 bytes is tag value 1 is for checksum
     int tagValue[11];     // the actual tag information +1 for adding null at string end
     led2=1;
     while(1)
        {//b->
        if (RFID.readable())
           {//->c
           pc.printf("Readable: %X\n\r", RFID.readable());
           led3=1;
           led1=0;           
           val = RFID.getc();
           if (val == 2)
              {//->d
              bytesRead = 0;
              for (bytesRead = 0; bytesRead < 12; bytesRead++)
                 {//-e
                 val = RFID.getc();
                 pc.printf("bytesRead: %X\n\r", bytesRead);
                 pc.printf("Tag READ: %X\n\r", val);
// In case the rfid module ever gets into a confused state, such as sending part
// of a sequence of tag values while the program was busy elsewhere, it checks
// each value to see whether it's a header or stop byte
                 if ((val == 0x0D) || (val == 0x0A) || (val == 0x03) || (val == 0x02))
                    {//f->
                    led2=0;
                    break;
                    }//f<-
// We store the tag ID in two different formats for convenience later in the program.
// The first format is as a series of raw values stored in a character array, with only the
// actual tag ID itself stored.  We don't want to include the checksum, so the program
// only appends the first 10 characters into elements 0 through 9 in the tagValue array.
                 if (bytesRead < 10)
                    {//f->
                    tagValue[bytesRead] = val;
                    }//f<-
// The second value requires some processing and then stores each value as a separate
// element in an array of bytes, so the program does some ASCII/HEX conversion to each
// value.
                 if ((val >= '0') && (val <= '9'))
                    {//f->
                    val = val - '0';
                    }//f<-
            else if ((val >= 'A') && (val <= 'F'))
                    {//f->
                    val = 10 + val - 'A';
                    }//f<-
// A byte is a total of 8 bits and can hold a value from 0 to decimal 255, while a hex 
// digit is a 4 bit value (half a byte) from 0 to F.  We can, therefore store two hex 
// digits in each byte as a pair of 4-bit values.
//
// The code first checks if it's dealing with the second hex digit of a pair.  If it
// is, the following comparison will be true.
                 if (bytesRead & 1 == 1)
                    {//f->
// This part of the code then deals with the second of a pair of hex digits.  It makes
// space for this digit in the current byte using a bitwise operator to shift the 
// existing 4 bits in that byte by 4 bits to the left leaving space for the second
// 4 bits to be set using the value in bytesRead.
                    tagBytes[bytesRead >> 1] = (val | (tempByte << 4));
// It then checks if it has reached the checksum byte, and if so calculates the checksum 
// using an XOR operation
                    if (bytesRead >> 1 != 5)
                       {//g->
                       checksum ^= tagBytes[bytesRead >> 1];
                       pc.printf("Checksum just after XOR %X\n\r", checksum);
                       };//g<-
// This part of the code then deals with the first of a pair of hex digits by simply
// putting the value directly into a variable.  This value will then be shifted 4 bits to
// the left on the next loop through by the code above.
                    }//f<-
                 else
                    {//f->
                    tempByte = val;
                    pc.printf("tempByte: %X\n\r", tempByte);
                    };//f<-
// The program them increments the counter that tracks how many bytes have been read and 
// reaches the end of the loop, going back to the start to check if it has finished reading
// all the digits yet.
                    bytesRead++;
                 }//e<-
// The program checks if 12 bytes have been read, indicating that it has a complete read and
// can move on to comparing the acquired value with its list of authorized tags.
              if (bytesRead == 12)
                 {//e->
                 led4=1;
                 tagValue[10] = '\0';
                 pc.printf("Tag Value: %X\n\r", tagValue);
                 pc.printf("Checksum: %X\n\r", (tagBytes[5]));
                 pc.printf(tagBytes[5] == checksum ? "--passed--":"--error--");
                 }//e<-   
              }//d<-
           }//c<-
        }//b<-
     }//a<-
//
int main()

    {//a->
    pc.printf("mbed Serial Terminal \n\r");
    wait(1);
    setup();
    loop();
    }//a<-

 

22 May 2010

Your tagValue is an array but you're outputting it as an integer. Thus what's printed is the address of variable and not its contents. Try the following:

1) change int tagValue[11]; into char tagValue[11]; 
2) change pc.printf("Tag Value: %X\n\r", tagValue); into pc.printf("Tag Value: %s\n\r", tagValue);
3) remove one of the bytesRead++; statements, as you have two of them and you get two increments per loop iteration.

The second change will tell the compiler that you want to print tagValue as a null-terminated string, i.e. a character array terminated with zero.

Another note is that your main is not exactly right (it doesn't make a difference in this program but might be important later). To mimic what Arduino does, it should be:

int main()
{
    setup();
    while (1)
    {
        loop();
    }
}

Basically, this code says: "Call setup() once and then keep calling loop() endlessly". while(1) is a shorthand for while(true) and thus produces an endless loop. In your code you are calling setup() before each loop(), and this can lead to problems in case your loop() routine returns.

P.S. It might be easier for others to read your code if you indent your curly braces one level less, like in my sample.

22 May 2010 . Edited: 22 May 2010

Thank you Igor

I will make the changes as you have suggested.  I really appreciate the explanation you have provided!

It seems to me that I added the second bytesRead++ statement because the program stopped at that point and did not enter the "if (bytesRead) == 12".  That may change with your suggestion regarding how to structure main().

I will also change the braces.  Your code is much easier to read.

Thanks again

Tim

Edited after changing program as suggested.

Thanks Igor!  Your changes sorted out my issues.  There was a line in the code that was intended to append a null string according to the book.  With the change to %s I have removed that line.

Now I will put back all of my code that displayed on the LCD and change this code to output there as well.

Your help is certainly appreciated.

Tim