Loading...
Logo
Processing Forum
Dear all,

I'm rather new with Arduino and Processing.

Please allow me to explain what my project is about:
I am using 3 units of Invensense MPU6000 6-axis accelerometer/gyroscope to make an inertial sensor network for gait analysis, interfaced with an Arduino Pro Mini.
The Arduino part is fine for me so far, so now comes the problem:

How do I interface it with Processing?

My aim is to acquire data from the serial port, and then plot a graph based on the values.

Data will be sent from the sensors via Arduino with Serial.write().

Thank you.

Replies(4)

Below is the Arduino code:

Copy code
  1. #include <SPI.h>
  2. #include <math.h>

  3. #define ToD(x) (x/131)
  4. #define ToG(x) (x*9.80665/16384)

  5. #define xAxis 0
  6. #define yAxis 1
  7. #define zAxis 2

  8. #define Aoffset 0.8

  9. //--- Settings /CS pins at pins 7, 8, and 9 ---//
  10. const int ChipSelPin1 = 7;
  11. const int ChipSelPin2 = 8;
  12. const int ChipSelPin3 = 9;

  13. int time=0;
  14. int time_old=0;

  15. float angle=0;
  16. float angleX=0;
  17. float angleY=0;
  18. float angleZ=0;

  19. //--- Setup for sensors ---//
  20. void setup()
  21. {
  22.   Serial.begin(115200);  // start the serial communication at baud rate of 115200
  23.   //Serial.println("MPU-6000 Data Acquisition");
  24.     
  25.   //--- SPI settings ---//
  26.   //Serial.print("Initializing SPI Protocol...");
  27.   SPI.begin();  // start the SPI library
  28.   SPI.setClockDivider(SPI_CLOCK_DIV2);  // setting SPI at 4Mhz
  29.   SPI.setBitOrder(MSBFIRST);  // data delivered MSB first
  30.   SPI.setDataMode(SPI_MODE0);  // latched on rising edge, transitioned on falling edge, active low
  31.   //Serial.println("SPI Initialized");
  32.   delay(50);
  33.   
  34.   //--- Configure the chip select pins as output ---//
  35.   pinMode(ChipSelPin1, OUTPUT);
  36.   pinMode(ChipSelPin2, OUTPUT);
  37.   pinMode(ChipSelPin3, OUTPUT);
  38.   
  39.   ConfigureMPU6000();  // configure chip
  40. }

  41. void loop()
  42. {
  43.   //time_old=time;
  44.   Serial.write(SPIread(0x3B,ChipSelPin1)); // AcceX1
  45.   Serial.write(SPIread(0x3C,ChipSelPin1)); // AcceX1
  46.   Serial.write(SPIread(0x3D,ChipSelPin1)); // AcceY1
  47.   Serial.write(SPIread(0x3E,ChipSelPin1)); // AcceY1
  48.   Serial.write(SPIread(0x3F,ChipSelPin1)); // AcceZ1
  49.   Serial.write(SPIread(0x40,ChipSelPin1)); // AcceZ1

  50.   Serial.write(SPIread(0x3B,ChipSelPin2)); // AcceX2
  51.   Serial.write(SPIread(0x3C,ChipSelPin2)); // AcceX2
  52.   Serial.write(SPIread(0x3D,ChipSelPin2)); // AcceY2
  53.   Serial.write(SPIread(0x3E,ChipSelPin2)); // AcceY2
  54.   Serial.write(SPIread(0x3F,ChipSelPin2)); // AcceZ2
  55.   Serial.write(SPIread(0x40,ChipSelPin2)); // AcceZ2

  56.   Serial.write(SPIread(0x3B,ChipSelPin3)); // AcceX3
  57.   Serial.write(SPIread(0x3C,ChipSelPin3)); // AcceX3
  58.   Serial.write(SPIread(0x3D,ChipSelPin3)); // AcceY3
  59.   Serial.write(SPIread(0x3E,ChipSelPin3)); // AcceY3
  60.   Serial.write(SPIread(0x3F,ChipSelPin3)); // AcceZ3
  61.   Serial.write(SPIread(0x40,ChipSelPin3)); // AcceZ3

  62.   //time=micros();
  63.   //int dt=time-time_old;
  64.   //Serial.print(dt);
  65.   //Serial.print("\n");
  66. }

  67. //***********************************************************//
  68. //-----------------------------------------------------------//
  69. //---------- Self-made functions for easier coding ----------//
  70. //-----------------------------------------------------------//
  71. //***********************************************************//

  72. //------------------------------------------//
  73. //--- Function for SPI writing to sensor ---//
  74. //------------------------------------------//
  75. void SPIwrite(byte reg, byte data, int ChipSelPin)
  76. {
  77.   uint8_t dump;
  78.   digitalWrite(ChipSelPin,LOW);
  79.   dump=SPI.transfer(reg);
  80.   dump=SPI.transfer(data);
  81.   digitalWrite(ChipSelPin,HIGH);
  82. }

  83. //--------------------------------------------//
  84. //--- Function for SPI reading from sensor ---//
  85. //--------------------------------------------//
  86. uint8_t SPIread(byte reg,int ChipSelPin)
  87. {
  88.   uint8_t dump;
  89.   uint8_t return_value;
  90.   uint8_t addr=reg|0x80;
  91.   digitalWrite(ChipSelPin,LOW);
  92.   dump=SPI.transfer(addr);
  93.   return_value=SPI.transfer(0x00);
  94.   digitalWrite(ChipSelPin,HIGH);
  95.   return(return_value);
  96. }

  97. //--------------------------------------//
  98. //--- Functions for reading raw data ---//
  99. //--------------------------------------//
  100. int AcceX(int ChipSelPin)
  101. {
  102.   uint8_t AcceX_H=SPIread(0x3B,ChipSelPin);
  103.   uint8_t AcceX_L=SPIread(0x3C,ChipSelPin);
  104.   int16_t AcceX=AcceX_H<<8|AcceX_L;
  105.   return(AcceX);
  106. }

  107. int AcceY(int ChipSelPin)
  108. {
  109.   uint8_t AcceY_H=SPIread(0x3D,ChipSelPin);
  110.   uint8_t AcceY_L=SPIread(0x3E,ChipSelPin);
  111.   int16_t AcceY=AcceY_H<<8|AcceY_L;
  112.   return(AcceY);
  113. }

  114. int AcceZ(int ChipSelPin)
  115. {
  116.   uint8_t AcceZ_H=SPIread(0x3F,ChipSelPin);
  117.   uint8_t AcceZ_L=SPIread(0x40,ChipSelPin);
  118.   int16_t AcceZ=AcceZ_H<<8|AcceZ_L;
  119.   return(AcceZ);
  120. }

  121. int GyroX(int ChipSelPin)
  122. {
  123.   uint8_t GyroX_H=SPIread(0x43,ChipSelPin);
  124.   uint8_t GyroX_L=SPIread(0x44,ChipSelPin);
  125.   int16_t GyroX=GyroX_H<<8|GyroX_L;
  126.   return(GyroX);
  127. }

  128. int GyroY(int ChipSelPin)
  129. {
  130.   uint8_t GyroY_H=SPIread(0x45,ChipSelPin);
  131.   uint8_t GyroY_L=SPIread(0x46,ChipSelPin);
  132.   int16_t GyroY=GyroY_H<<8|GyroY_L;
  133.   return(GyroY);
  134. }

  135. int GyroZ(int ChipSelPin)
  136. {
  137.   uint8_t GyroZ_H=SPIread(0x47,ChipSelPin);
  138.   uint8_t GyroZ_L=SPIread(0x48,ChipSelPin);
  139.   int16_t GyroZ=GyroZ_H<<8|GyroZ_L;
  140.   return(GyroZ);
  141. }

  142. //-------------------------------------------//
  143. //--- Function to initialize MPU6000 chip ---//
  144. //-------------------------------------------//
  145. void ConfigureMPU6000()
  146. {
  147.   //Serial.println("Configuring sensors......");
  148.   // DEVICE_RESET @ PWR_MGMT_1, reset device
  149.   SPIwrite(0x6B,0x80,ChipSelPin1);
  150.   delay(150);
  151.   SPIwrite(0x6B,0x80,ChipSelPin2);
  152.   delay(150);
  153.   SPIwrite(0x6B,0x80,ChipSelPin3);
  154.   delay(150);
  155.   // TEMP_DIS @ PWR_MGMT_1, wake device and select GyroZ clock
  156.   SPIwrite(0x6B,0x03,ChipSelPin1);
  157.   delay(150);
  158.   SPIwrite(0x6B,0x03,ChipSelPin2);
  159.   delay(150);
  160.   SPIwrite(0x6B,0x03,ChipSelPin3);
  161.   delay(150);
  162.   // I2C_IF_DIS @ USER_CTRL, disable I2C interface
  163.   SPIwrite(0x6A,0x10,ChipSelPin1);
  164.   delay(150);
  165.   SPIwrite(0x6A,0x10,ChipSelPin2);
  166.   delay(150);
  167.   SPIwrite(0x6A,0x10,ChipSelPin3);
  168.   delay(150);
  169.   // SMPRT_DIV @ SMPRT_DIV, sample rate at 1000Hz
  170.   SPIwrite(0x19,0x00,ChipSelPin1);
  171.   delay(150);
  172.   SPIwrite(0x19,0x00,ChipSelPin2);
  173.   delay(150);
  174.   SPIwrite(0x19,0x00,ChipSelPin3);
  175.   delay(150);
  176.   // DLPF_CFG @ CONFIG, digital low pass filter at 42Hz
  177.   SPIwrite(0x1A,0x03,ChipSelPin1);
  178.   delay(150);
  179.   SPIwrite(0x1A,0x03,ChipSelPin2);
  180.   delay(150);
  181.   SPIwrite(0x1A,0x03,ChipSelPin3);
  182.   delay(150);
  183.   // FS_SEL @ GYRO_CONFIG, gyro scale at 250dps
  184.   SPIwrite(0x1B,0x00,ChipSelPin1);
  185.   delay(150);
  186.   SPIwrite(0x1B,0x00,ChipSelPin2);
  187.   delay(150);
  188.   SPIwrite(0x1B,0x00,ChipSelPin3);
  189.   delay(150);
  190.   // AFS_SEL @ ACCEL_CONFIG, accel scale at 2g (1g=8192)
  191.   SPIwrite(0x1C,0x00,ChipSelPin1);
  192.   delay(150);
  193.   SPIwrite(0x1C,0x00,ChipSelPin2);
  194.   delay(150);
  195.   SPIwrite(0x1C,0x00,ChipSelPin3);
  196.   delay(150);
  197.   // DATA_RDY_EN @ INT_ENABLE, enable Data Ready interrupt
  198.   SPIwrite(0x38,0x01,ChipSelPin1);
  199.   delay(150);
  200.   SPIwrite(0x38,0x01,ChipSelPin2);
  201.   delay(150);
  202.   SPIwrite(0x38,0x01,ChipSelPin3);
  203.   delay(150);
  204.   // INT_RD_CLEAR @ INT_PIN_CFG, interrupt cleared on any read operation
  205.   SPIwrite(0x37,0x10,ChipSelPin1);
  206.   delay(150);
  207.   SPIwrite(0x37,0x10,ChipSelPin2);
  208.   delay(150);
  209.   SPIwrite(0x37,0x10,ChipSelPin3);
  210.   delay(150);
  211.   //Serial.println("Sensors configured");
  212. }
Hey,

you can use serialEvent() to read the data in processing.
I usually use print() / println() to send the data, because it's easier to seperate the values, when you have strings.
So my advice is to send the values seperated by spaces and a linebreak at the end.
Then in processing you can read one line at a time and split it into the single values. An example:
Copy code
  1. import processing.serial.*;
    Serial port;

    void setup() {
      println(Serial.list());
      // you might have to pick a different serial-port here
      port = new Serial(this, Serial.list()[0], 9600);
    }

    void draw() {
      // do what ever you want here
    }

    // serial event
    void serialEvent(Serial p) {
      // get message till line break (ASCII > 13)
      String message = p.readStringUntil(13);
      // just if there is data
      if (message != null) {

        String[] elements;
        // try catch function because of possible garbage in received data
        try {
          elements = splitTokens(message);
          // loop through sensor values
          for (int i =0; i < elements.length && i < elements.length; i++ ) {
            print(int(elements[i]));
            print(" ");
          }
          println();
        }
        catch (Exception e) {
        }
      }
    }

Hi Benja,

Thank you so much for your help and swift reply.

The reason I was using Serial.write() rather than Serial.print() in Arduino is due to the fact the Serial.print() slows the system down, while I need a much fast sampling rate (200Hz).
Sure sending pure bytes can be a bit faster, but you have the problem how to seperate the values. Because you can't know at what point processing connects to the serial-port, it could happen that the first byte you recieve is not the first value from your sensor. Therefore you would have to send a special byte-value in between every set of values to mark the end of a message. And this might be a problem if the values from your sensor can also become the value that you are sending as seperator.

Maybe you could change your arduino code, so that it waits until processing is ready to recieve data and sends some command. And then start sending the values.

Did you really notice a big slowdown, when using print()? When picking a high baud-rate, e.g. 115200, and want to send values 200 times a second, you still have 576 symbols for your message, which should be more than enough for the 12 sensor-vaules.
What you should not try is to trace all recieved values in processing, because that can really slow down the system.