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

Thread: Error when serial.print() to LabVIEW in interrupt

  1. #1

    Error when serial.print() to LabVIEW in interrupt

    Hi everyone!
    I'm trying to acquire two analog signals @1kHz, my fixed sampling frequency.
    To accomplish this i'm using the library IntervalTimer and calling a function every 1000 microseconds.
    The next step that i cannot manage to do is to collect this live stream of data while
    displaying it in LabVIEW (I'm using VISA).

    This is the code written and uploaded on teensy 3.2 with Teensy Loader 1.40,
    Teensyduino version 1.40 installed over Arduino IDE 1.8.3:

    Code:
    //  Acquisition & display variables
    IntervalTimer myTimer; // Create an IntervalTimer object
    const int Ch0 = A0;    // the pin with analog input (Channel 0)
    const int Ch1 = A1;    // the pin with analog input (Channel 1)
    float val_Ch0 = 0;     // the value read from Channel 0 (16 bit)
    float val_Ch1 = 0;     // the value read from Channel 1 (16 bit)
    float volts_Ch0 = 0;   // value of Channel 0 in volts
    float volts_Ch1 = 0;   // value of Channel 1 in volts
    
    // Processing variables
    int counter_ms = 0;
    int counter_s = 0;
    
    /////////////
    //  Setup  //
    /////////////
    
    void setup(void) {
      pinMode(Ch0, INPUT);
      pinMode(Ch1, INPUT);
      analogReadResolution(16);
      Serial.begin(9600);
      delay(3000);
      myTimer.begin(ChnlsReadPrint, 1000); // function executed every 1000 us
    }
    
    
    /////////////////////////////////////////////////////////////////////
    //  ChnlsReadPrint() is a function called inside an interrupt.     //
    //  Is called every 1000 microseconds and performs these tasks:    //
    //  - Acquire two analog channels;                                 //
    //  - Converts the values in volts;                                //
    //  - write them together with the time;                           //
    /////////////////////////////////////////////////////////////////////
    
    void ChnlsReadPrint(void) {
      val_Ch0 = analogRead(Ch0);                // read Channel 0
      val_Ch1 = analogRead(Ch1);                // read Channel 1
      volts_Ch0 = val_Ch0 * 3.3 / pow(2, 16);   // conversion to volts
      volts_Ch1 = val_Ch1 * 3.3 / pow(2, 16);   // conversion to volts
    
      counter_ms += 1;
      if (counter_ms > 999) {
        counter_ms = 0;
        counter_s += 1;
      }
      String stringOne = String(counter_s, DEC);
      String stringTwo = String(counter_ms, DEC);
      String stringThree = String(volts_Ch0, 4);
      String stringFour = String(volts_Ch1, 4);
      String stringTot = String(stringOne + " " + stringTwo + " " + stringThree + " " + stringFour);
      Serial.print(stringTot);
      Serial.print("\r\n");
      Serial.flush();
    
    }
    
    ////////////////////////////////////////
    //  The main program will do nothing  //
    ////////////////////////////////////////
    
    void loop(void) {
    }
    
    
    ////////////////////////////////////////
    //            END OF FILE             //
    ////////////////////////////////////////
    This code works until it happens the "jump" depicted in the following picture:

    Click image for larger version. 

Name:	LabviewProblem2.PNG 
Views:	21 
Size:	81.7 KB 
ID:	11981
    Click image for larger version. 

Name:	LabviewProblem3.PNG 
Views:	24 
Size:	74.8 KB 
ID:	11982

    What LabVIEW does is simply:
    - reading the serial port with VISA and obtaining a new line with a string
    - split the string received into 4 numbers (2 integers and 2 float)
    - append each new value into arrays
    - plot the array in a xy graph.

    Here is the Block Diagram:

    Click image for larger version. 

Name:	LabviewProblem.jpg 
Views:	26 
Size:	70.3 KB 
ID:	11983

    I cannot figure out why these jumps happen after tens of thousands of strings...
    Thank you in advance,
    Leo

  2. #2
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    18,160
    First, try slowing the speed to only 20 or 100 per second.

    My guess is Labview just can't keep up with this speed on a sustained basis. Eventually all the buffers between Serial.print() and Labview acquiring the data fill up, and somewhere something has to give (delete data).

    So the first step is to check if much slower speed works, so you can know whether to focus your effort at improving the speed, or whether there is some bug happening which loses data even when running slowly.

    If it does turn out the be speed related, then you're going to have to do something to improve the speed for Labview can keep up. Long ago the Arduino Serial Monitor had these same sorts of problems. I put quite a lot of work into improvements, which eventually became part of modern Arduino versions. The main thing that helped was not updating the GUI for every new line of incoming data. Instead, I put a 30 Hz timer into the code. Incoming data was instead just appended to a buffer, and then the buffer contents were used to update the GUI at 30 Hz. Redrawing graphics is incredibly CPU intensive, so if you're asking Labview to do that 1000 times per second, simply storing the data into an array and doing the graph update for every 20, 33, 50 or even 100 measurements will probably help dramatically. In the Arduino IDE, the other CPU critical issue was parsing full USB rate data into lines, partly because Java is inefficient (probably probably still a lot faster than Labview) and partly because Java does quite a lot of special character for non-ASCII characters, which I never did figure out how to turn off. Whether those lessons I learned with Java apply for Labview is a good question.... but before going down this optimization path, first at least do careful testing at slower speeds to figure out if the data loss really is speed related, or some sort of bug that doesn't depend on speed.

    If this is a well funded commercial project being done with billable hours, as many Labview uses often are, the other possible speed "optimization" that might be more cost effective would involve just throwing an insanely powerful PC at the problem!

  3. #3
    ahah if only i had money! (No pressure to learn )
    Thanks so much for the fast reply, I'm amazed by your kindness.
    I will try to follow your suggestions and update the results!

  4. #4
    Senior Member duff's Avatar
    Join Date
    Jan 2013
    Location
    Las Vegas
    Posts
    909
    Labview actually has quite advanced serial modifications that can greatly speed up the overall VI, check out the Advanced Serial Example. Another thing is using the consumer-producer model that Labview has many examples for so you can make large serial buffer in the consumer loop that is read in the producer loop. Also look at the Serial examples where you can set the delimiters and such in the serial setup part before it runs any loops. Another is you are appending all your data to be read on your front panel with the capturing of serial data, move writing data to the graph and response block to a producer loop at lower a priority and slower update rate than the consumer loop and possibly dump old data in the response block so that it does not consume to much memory.

Posting Permissions

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