0

I have the following code that reads a RFID reader, it was working perfect without any dealy and then I try to an analog read from a potentiometer using analogRead.

The analog read works fine but then when I hover the card over the RFID it takes about 7 seconds or so to go into the line where I turn on a LED.

Im sure Im doing something wrong with analogReader because this is the first time I use it.

I really appreciate any help

    #include <MicroView.h>

    MicroViewWidget *widget;        // create widget pointer

    #define MAX_BITS 100                 // max number of bits 
    #define WEIGAND_WAIT_TIME  3000      // time to wait for another weigand pulse.  

    unsigned char databits[MAX_BITS];    // stores all of the data bits
    unsigned char bitCount;              // number of bits currently captured
    unsigned char flagDone;              // goes low when data is currently being captured
    unsigned int weigand_counter;        // countdown until we assume there are no more bits

    unsigned long facilityCode=0;        // decoded facility code
    unsigned long cardCode=0;            // decoded card code


    int sensorPin = A1;    // select the input pin for the potentiometer
    int sensorValue = 0;  // variable to store the value coming from the sensor

    // interrupt that happens when INTO goes low (0 bit)
    void ISR_INT0()
    {

      bitCount++;
      flagDone = 0;
      weigand_counter = WEIGAND_WAIT_TIME;  

    }

    // interrupt that happens when INT1 goes low (1 bit)
    void ISR_INT1()
    {

      databits[bitCount] = 1;
      bitCount++;
      flagDone = 0;
      weigand_counter = WEIGAND_WAIT_TIME;  
    }

    void setup()
    {

      pinMode(2, INPUT_PULLUP);     // DATA0 (INT0)
      pinMode(3, INPUT_PULLUP);     // DATA1 (INT1)
      pinMode(5, OUTPUT);           // LED

      Serial.begin(9600);

      // binds the ISR functions to the falling edge of INTO and INT1
      attachInterrupt(0, ISR_INT0, FALLING);  
      attachInterrupt(1, ISR_INT1, FALLING);

      digitalWrite(sensorPin, HIGH);      // Internal Pull-up
      pinMode(sensorPin, INPUT);          // make pin as INPUT

      uView.begin();                      // start MicroView
      uView.clear(PAGE);                  // clear page
       uView.setCursor(5,0);
      uView.print("TEST");
       uView.setCursor(0,20);
       uView.print("RFID READ");
      widget = new MicroViewSlider(0, 35, 0, 1024);    // make widget as Slider
      //widget2 = new MicroViewSlider(0, 20, 0, 1024, WIDGETSTYLE1);    // make widget as Silder STYLE1
      uView.display();                    // display the content in the screen buffer   

      weigand_counter = WEIGAND_WAIT_TIME;
    }

    void loop()
    {

      // This waits to make sure that there have been no more data pulses before processing data
      if (!flagDone) {
        if (--weigand_counter == 0)
          flagDone = 1;  
      }

//****** THIS IS THE NEW CODE THAT FREEZE FOR ABOUT 7 SECONDS THE PROGRAM ***//    
      sensorValue = analogRead(sensorPin);    // read sensorPin
      widget->setValue(sensorValue);          // set value of sensorPin to widget
      //widget2->setValue(sensorValue);         // set value of sensorPin to widget 
      uView.display(); 

//****** THIS IS THE NEW CODE THAT FREEZE FOR ABOUT 7 SECONDS THE PROGRAM ***//


      // if we have bits and we the weigand counter went out
      if (bitCount > 0 && flagDone) {
        unsigned char i;

        Serial.print("Read ");
        Serial.print(bitCount);
        Serial.print(" bits. ");



        if (bitCount == 32){

          // **** AFTER 7 SECONDS I GET INTO THIS CODE ****///

          uView.clear(PAGE);      // clear the page buffer
          uView.setCursor(0,0);

          digitalWrite(5, HIGH);


        }


         // cleanup and get ready for the next card
         bitCount = 0;
         facilityCode = 0;
         cardCode = 0;
         for (i=0; i<MAX_BITS; i++) 
         {
           databits[i] = 0;
         }
      }
    }
1

analogRead() is fine, it takes only about 110 µs, but there are several other issues with your code that you should fix:

  1. Any variable that is shared between interrupt code and normal code should be declared volatile in order to prevent the compiler to do some unsafe optimizations.

  2. Any such variable that is more than one byte in size should be accessed from the main program with interrupts disabled.

  3. You should take care of not writing into databits[] past the end of the array.

  4. Counting loop iterations is a very bad way of measuring elapsed time, as the counting speed will change whenever you change your loop code. Use micros() instead.

There is also an issue with how you use flagDone. You set it to 1, then you call analogRead(), MicroViewSlider::setValue() and uView.display(), then you read it back. What if your ISR has set it back to 0 in the meantime? I suspect this is the main cause of the problem you see.

I suggest you use flagDone to inhibit the ISRs: the main loop sets it to true to tell the ISRs “Let's say we are done with this card. Please do not touch anything while I process the already received information.” And later it sets it to false meaning “You can proceed reading bits now.”

Given the above considerations, I would try something along these lines:

volatile bool flagDone;     // if we are done, pause the reading
volatile uint8_t bitCount;  // number of bits received so far
volatile uint32_t rxTime;   // last time we got a bit

// Interrupt that happens when INTO goes low (0 bit).
void ISR_INT0()
{
    if (!flagDone && bitCount < MAX_BITS) {
        rxTime = micros();
        databits[bitCount++] = 0;
    }
}

// Same thing, but writes 1 instead of 0 into databits[].
void ISR_INT0() { ... }

void loop()
{
    // Safely read rxTime.
    noInterrupts();
    uint32_t rxTimeCopy = rxTime;
    interrupts();

    if (bitCount > 0 && micros() - rxTimeCopy >= WEIGAND_WAIT_TIME) {
        // Assume we are done reading this card.
        flagDone = true;

        // Do whatever with databits[].
        // ...

        // Get ready for the next card.
        bitCount = 0;
        flagDone = false;  // do this last: it re-enables the ISR
    }
}
3
  • Appreciate it I will give a try. Do you recommend me to use ArduinoThread library instead?
    – VAAA
    May 18 '17 at 17:32
  • @VAAA: Not sure I understand in which way you expect ArduinoThread to help here... May 18 '17 at 17:40
  • you are totally right Im very sorry Im new and I have to understand a lot of things before asking dumb questions. Let me understand your code first :)
    – VAAA
    May 18 '17 at 22:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.