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

Thread: How To Maintain Frequency Sampling in Data Acquisition Using Teensy 3.5 and Saving it

  1. #1
    Junior Member
    Join Date
    Nov 2019
    Posts
    11

    How To Maintain Frequency Sampling in Data Acquisition Using Teensy 3.5 and Saving it

    I have an ongoing project using Teensy 3.5 as a DAQ and I would like to acquire values of two sensors and its time stamp/ millis(). The sensors I'm using is Olimex Shield-EKG/EMG Rev. B for my EMG data and optical encoder (Yumo E6B2 -CWZ3E 1024P/R). I need to save the data to a csv files with a consistent frequency sampling and within a certain range of time like 60s, 120s, or so on. I've succeeded in reading the sensor values but I haven't find a way to save the data well.

    I have tried the Processing but it didn't save the data accurately (like the values produce isn't accurate, there's s since the frequency sampling for the Teensy 3.5 is around 3000-ish Hz. Is there any suggestion how I should the data, what app I should use or so on?

    Below is my Arduino code to read the data an send it to Processing

    Code:
    /*
      pengambilanData - Remake
    
      Data taken from encoder and EMG and send to Processing. 
      Sensor values data type is INT
      
    */
    #include <SoftwareSerial.h>
    #include <FrequencyTimer2.h>
    #define outputA 5 //untuk encoder
    #define outputB 6 
    #define RawEMG A0 //analog pin for EMG
    int counter = 0;
    int derajat = 0;
    int EMG;
    int aState;
    int aLastState;
    
    void setup() {
      pinMode (outputA, INPUT_PULLUP);
      pinMode (outputB, INPUT_PULLUP);
      Serial.println("CLEARDATA"); //clear all rows and columns
      Serial.println("LABEL,Computer Time,Milisec,Counter, Derajat, EMG");
    //  FrequencyTimer2::setPeriod(500);
    //  FrequencyTimer2::enable();
    
      Serial.begin(9600);
      //Reads the initial state of the outputA
      aLastState = digitalRead(outputA);
    }
    
    void loop() {
      int waktu = millis();
      EMG = analogRead (RawEMG); //reads EMG sensor
      //float EMG = EMG * (5.0 / 1023.0);
      aState = digitalRead(outputA); //reads the 'current' state of the outputA
      //if outputB state is different to the outputA state, that means the encoder is rotating clockwise
      if (aState != aLastState){
        //if outputB state is different to the outputA state, that means the encoder is rotating clockwise
        if (digitalRead(outputB) != aState){
          counter ++;
        } else {
          counter --;
        }
        if (counter > 2048 or counter < -2048) //omron sebelumnya 1200 yang 600ppr, resolusi x 2
        {
          counter = 0;
        }
        derajat = counter * 360/2048;
    
        //print over the serial line to send to Processing. To work with the processisng sketch we provide, 
        //follow this easy convention: separate each sensor value with a comma, and separate each cycle of loop with a newline character.
        //Remember to separate each sensor value with a comma. Print every value and comma using Serial.print(), except the last sensor value. 
        //For the last sensor value, use Serial.println()
      }
       aLastState = aState;
       Serial.print(counter);
       Serial.print(",");
       Serial.print(derajat);
       Serial.print(",");
       Serial.println(EMG);
       
      }
    While this is the Processing code I use, it work well but it didn't save the data the way I wanted it to be. I would be grateful for any suggestions.

    Code:
    import processing.serial.*;
    Serial myPort; //creates a software serial port on which you will listen to Arduino
    Table dataTable; //table where we will read in and store values. You can name it something more creative!
    
    int numReadings = 12000 ; //keeps track of how many readings you’d like to take before writing the file.
    int readingCounter = 0; //counts each reading to compare to numReadings.
    int atime = millis(); //waktu awal
    int btime = 0; //waktu yang akan dicompare
    int batas = 15000;
    
    
    String fileName, val;
    void setup()
    {
      String portName = Serial.list()[1]; //teensy port 1, Arduino port 5
      //CAUTION: your Arduino port number is probably different! Mine happened to be 1. Use a “handshake” sketch to figure out and test which port number your Arduino is talking on. A “handshake” establishes that Arduino and Processing are listening/talking on the same port.
      //Here’s a link to a basic handshake tutorial: https://processing.org/tutorials/overview/
    
      myPort = new Serial(this, portName, 9600); //set up your port to listen to the serial port
      dataTable = new Table();
    
      dataTable.addColumn("id"); //This column stores a unique identifier for each record. We will just count up from 0 – so your first reading will be ID 0, your second will be ID 1, etc.
    
      //the following adds columns for time. You can also add milliseconds. See the Time/Date functions for Processing: https://www.processing.org/reference/
      dataTable.addColumn("hour");
      dataTable.addColumn("minute");
      dataTable.addColumn("second");
      dataTable.addColumn("milisec");
    
      //the following are dummy columns for each data value. Add as many columns as you have data values. Customize the names as needed. Make sure they are in the same order as the order that Arduino is sending them!
      dataTable.addColumn("Counter");
      dataTable.addColumn("Sudut");
      dataTable.addColumn("EMG");
    }
    
    void serialEvent(Serial myPort) {
      try {
        val = myPort.readStringUntil('\n'); //The newline separator separates each Arduino loop. We will parse the data by each newline separator.
        if (val!= null) { //We have a reading! Record it.
          val = trim(val); //gets rid of any whitespace or Unicode nonbreakable space
          println(val); //Optional, useful for debugging. If you see this, you know data is being sent. Delete if you like.
          int sensorVals[] = int(split(val, ',')); //parses the packet from Arduino and places the valeus into the sensorVals array. I am assuming floats. Change the data type to match the datatype coming from Arduino.
    
          TableRow newRow = dataTable.addRow(); //add a row for this new reading
          newRow.setInt("id", dataTable.lastRowIndex());//record a unique identifier (the row’s index)
    
          //record time stamp
          newRow.setInt("hour", hour());
          newRow.setInt("minute", minute());
          newRow.setFloat("second", second());
          newRow.setInt("milisec", millis());
    
          //record sensor information. Customize the names so they match your sensor column names.
          newRow.setFloat("Counter", sensorVals[0]);
          newRow.setFloat("Sudut", sensorVals[1]);
          newRow.setFloat("EMG", sensorVals[2]);
          readingCounter++; //optional, use if you’d like to write your file every numReadings reading cycles
          btime = millis();
          
          //saves the table as a csv in the same folder as the sketch every numReadings.
          if (readingCounter % numReadings ==0)//The % is a modulus, a math operator that signifies remainder after division. The if statement checks if readingCounter is a multiple of numReadings (the remainder of readingCounter/numReadings is 0)
          {
            fileName = "DATA_odi2kg_(TEST3)"+ str(year())+"_" + str(month())+"_" + str(day()) +"_"+ str(dataTable.lastRowIndex()); //this filename is of the form year+month+day+readingCounter
            saveTable(dataTable, "G:/My Drive/Amelia's Data/KULIAH/. SKRIPSI/.PENGAMBILAN DATA/Data/"+ fileName + ".csv", "csv"); //Woo! save it to your computer. It is ready for all your spreadsheet dreams.
            exit();
          }
          //if (btime - atime > batas)
          //{
          //  fileName = "DATA_odi2kg_(9.1)test"+ str(year())+"_" + str(month())+"_" + str(day()) +"_"+ str(dataTable.lastRowIndex()); //this filename is of the form year+month+day+readingCounter
          //  saveTable(dataTable, "G:/My Drive/Amelia's Data/KULIAH/. SKRIPSI/.PENGAMBILAN DATA/Data/"+ fileName + ".csv", "csv"); //Woo! save it to your computer. It is ready for all your spreadsheet dreams.
          //  exit();
          //}
        }
       
      }
    
      catch(RuntimeException e) {
        e.printStackTrace();
      }
    }
    
    void draw()
    {
      //visualize your sensor data in real time here! In the future we hope to add some cool and useful graphic displays that can be tuned to different ranges of values.
    }

  2. #2
    Senior Member
    Join Date
    Nov 2017
    Location
    Belgium
    Posts
    152
    I did not try your code but if you want to use the print statement to send floats you need to be aware that by default it will only send 2 digits after the decimal point.
    If you want more decimal places you need to specify how many.
    Code:
    float EMG;
    Serial.println(EMG);    //print 2 decimal places
    Serial.println(EMG, 8); //print 8 decimal places

  3. #3
    Junior Member
    Join Date
    Nov 2019
    Posts
    11
    I see, thank you for the suggestion. I will keep that in mind. Actually I should have establish EMG as an integer since the sensors reading didn't have any decimals.

Posting Permissions

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