Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 5 of 5

Thread: attachInterrupt() corrupting Serial buffer requiring Serial restart

  1. #1
    Junior Member
    Join Date
    Oct 2017
    Posts
    14

    attachInterrupt() corrupting Serial buffer requiring Serial restart

    I am working on a proof-of-concept ADC to "explode" what's inside of an ADC chip for teaching purposes.

    Currently, I have a sketch that uses a push-button to act as a clock-pulse that counts up (1, 2, 3, 4, ...) for every positive edge using the attachInterrupt() function.

    The sketch works great to view the data in the serial monitor.

    I am pairing the Arduino (Teensy 3.2) with a Raspberry Pi configured to read data off the Serial line to a text box.

    After a good bit of troubleshooting it appears that the attachInterrupt() function corrupts the Serial buffer with garbage for every interrupt. For instance, if I use

    Code:
    Serial1.flush();
    Serial1.begin(115200);
    immediately after the interrupt and then send out my data using Serial.println() I get my expected decimal value at my output. However, without these lines I just get unicode garbage at my Serial output. See full "fixed" sketch code below:

    My question is: why is this happening? I should not need to restart Serial every iteration of the clock.

    Code:
    #define HWSERIAL Serial1
    
    const int numBits = 12;             //Number of bits in ADC (resolution)
    const int comparatorPin = 14;       //Pin number of comparator out
    const int clockPin = 15;            //Pin number of external clock (square wave) input; expecting clock with 50% duty-cycle
    volatile int comparatorState = 0;   //Is comparator high or low?
    volatile bool clockState = 0;       //Is clock high or low?
    volatile int masterCount = 0;       //Our master count
    volatile bool isSameVal = false;    //Is the value of the master count the same value as last cycle?
    
    int outVal = 0;
    
    int masterBinCount[12];     //Array to store binary value of the master count
    byte outputPins[12];        //Array to store the numbers associated with the output pin numbers
    int maxValue = 0;           //Initialize max counter value to zero
    
    void setup() {
      Serial.begin(115200);       //Begin Serial transmission
      HWSERIAL.begin(115200, SERIAL_8N1);
      HWSERIAL.flush();
      delay(2000);
    
      defineOutPins(outputPins);  //Assign pin numbers for output pins
    
      pinMode(14, INPUT);   //Comparator Pin
      pinMode(15, INPUT);   //Clock-in pin
    
      maxValue = pow(2, numBits);   //Set max counter value to max bit resolution. Ex. for 12 bits --> 4096
    }
    
    void loop() {
      attachInterrupt(clockPin, doOnClock, RISING);   //When clock is on a positive-edge execute doOnClock function
    
      HWSERIAL.flush();
      HWSERIAL.begin(115200);
    
      if(isSameVal == false) {    //If the master count is NOT the same as the last cycle
        convertDecToBin();        //Convert the master count (dec) to binary
        binaryToPins();           //Send the binary value (via digitalWrite) to output pins
      }
      else {
        //Do nothing
      }
      delay(1000);
    }
    
    void defineOutPins(byte pinNos[]) {   //Assign pin numbers to parallel binary out: Teensy 3.2 pin #0 --> #11
      for(byte i = 0; i < numBits; i++) {
        pinNos[i] = {i};      //Assign current pin this value
        pinMode(i, OUTPUT);   //Define pins as outputs
      } 
    }
    
    void doOnClock() {
      comparatorState = digitalRead(comparatorPin);   //Check comparator state
    
      if(comparatorState >= 0.5) {            //Check if positive clock pulse
        if(masterCount == (maxValue - 1)) {   //Check if current count value is at "ceiling"
          //Do nothing
        }
        else {            //Else increment count up
          masterCount++;
        }
      }
      else if(comparatorState < 0.5) {    //Check if negative clock pulse
        if(masterCount == 0) {            //Check if current count value is at "floor"
          //Do nothing
        }
        else {
          masterCount--;    //Else decrment count down
        }
      }
    
      isSameVal = false;    //Set "finished" counting for this clock-pulse
    }
    
    void convertDecToBin() {
      for(int j = 0; j < numBits; j++) {
        int tempCnt = bitRead(masterCount, j);
        masterBinCount[numBits - (j+1)] = tempCnt;    //Populate the master binary count array in "reverse" order starting with the LSB at the highest array index
      }
    }
    
    void binaryToPins() {
      for(int e = 0; e < numBits; e++) {
        //digitalWrite(outputPins[e], masterBinCount[e]);   //Write our master binary value to output pins
        //Serial.print(masterBinCount[e]);                    //THIS LINE IS FOR TROUBLESHOOTING!!
      }
      isSameVal = true;       //Tell program we wrote the master count to the pins for this clock cycle
    
      outVal = masterCount;
    
      Serial.println(outVal);
      HWSERIAL.println(outVal);
    
      //Serial.print(" decimal: ");   //THIS LINE IS FOR TROUBLESHOOTING!!
      //Serial.print(masterCount);    //THIS LINE IS FOR TROUBLESHOOTING!!
      //Serial.println("");           //THIS LINE IS FOR TROUBLESHOOTING!!
    }

  2. #2
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    8,321
    First step would be to do these only once in setup() - remove this code from loop():
    Code:
      attachInterrupt(clockPin, doOnClock, RISING);   //When clock is on a positive-edge execute doOnClock function
    
      HWSERIAL.flush();
      HWSERIAL.begin(115200);
    The attach is persistent

    The .begin is also persistent after it sets up the hardware. Doing it again will cause a reset in some fashion and may be the trouble.

    You can test this to work by wiring Serial1 to Serial2 ( crossing RX<>Tx, or a second Teensy ) and verify the transfer works.

    Teensy only sends what it is given - not sure what happens on the RasPi

  3. #3
    Senior Member
    Join Date
    Feb 2017
    Posts
    275
    Why are you calling attachInterrupt() on every pass through loop?

    ‘comparatorState’ variable does not need to be ‘volatile’ or global, it can be local to ‘doOnClock()’. It also doesn’t need to be an ‘int’, ‘uint8_t’ would be fine. Why compare it to 0.5? it can ONLY be 1 or 0.

  4. #4
    Junior Member
    Join Date
    Oct 2017
    Posts
    14
    Quote Originally Posted by defragster View Post
    First step would be to do these only once in setup() - remove this code from loop():
    Code:
      attachInterrupt(clockPin, doOnClock, RISING);   //When clock is on a positive-edge execute doOnClock function
    
      HWSERIAL.flush();
      HWSERIAL.begin(115200);
    The attach is persistent

    The .begin is also persistent after it sets up the hardware. Doing it again will cause a reset in some fashion and may be the trouble.

    You can test this to work by wiring Serial1 to Serial2 ( crossing RX<>Tx, or a second Teensy ) and verify the transfer works.

    Teensy only sends what it is given - not sure what happens on the RasPi
    Yes! You are correct, thank you for pointing that out. I think you are helping me down the right path because I think the only reason why I could "force" it to work by force-restarting the Serial in the loop is because of the innate "reset" resulted in a random transient that matched my expected results.

    Quote Originally Posted by gfvalvo View Post
    Why are you calling attachInterrupt() on every pass through loop?

    ‘comparatorState’ variable does not need to be ‘volatile’ or global, it can be local to ‘doOnClock()’. It also doesn’t need to be an ‘int’, ‘uint8_t’ would be fine. Why compare it to 0.5? it can ONLY be 1 or 0.
    Thank you for pointing that out as well! I wouldn't have have caught that error. I chose fix-points on either side of 0.5 to mitigate any potential misreadings or voltage sag that could somehow result in my "check" value a bit above or below the expected logic levels in 3.3v. Like you suggest, it's basically impossible if I designed everything properly but I'm developed a habitual wariness of EQUALS statements over the years for anything that takes place outside of a software app.

  5. #5
    Senior Member
    Join Date
    Feb 2017
    Posts
    275
    Quote Originally Posted by mcooi77 View Post
    I'm developed a habitual wariness of EQUALS statements over the years for anything that takes place outside of a software app.
    "Equals Comparisons" are fine for integer-type variables.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •