Arduino+Processing Problem: ArrayIndexOutOfBounds

edited October 2015 in Arduino

Hi Everyone, i've been working on a little program combining arduino and processing aiming at generating visuals from movement ( gyroscope + vibration sensor).

So far I tested both the gyroscope and the vibration sensor separately and it worked just fine. Since I've tried to combine them i've been getting this error message: ArrayIndexOutOfBoundsException: 1 and the line 53: float roty = (sensors[1]*10); is highlighted at the same time

I assume there is a problem with myString content, or I guess with the string access and my sensors declaration but I can't figure out what to do. I've been learning code for a very short time, please have mercy on my inaccuracies ^^
(i'm french so comments are mostly in french,let me know if you need me to explain myself) Thank you so much for your help !!!

    import glitchP5.*; //import Glitch P5
    String portName = "/dev/cu.usbmodem1421"; 
    import processing.serial.*;
    String serial; 
    Serial myPort;
    int linefeed = 10; 
    int numSensors = 3; 
    float[] sensors;
    float[] pSensors;
    float bornexinf=0; 
    float bornexsup=0;
    float borneyinf=0; 
    float borneysup=0; 
    float rotxold=0; 
    float rotyold=0; 
    // vibration
    int end = 10;    //Le nombre 10 en ASCII pour linefeed marquant la fin du serial.println
    GlitchP5 glitchP5; // declare an instance of GlitchP5. only one is needed
    int j=0; //variable d'incrémentation carré dans carré
    int max=1; //nombre d'itération, soit le nb de carrés dans le carré
    int longueur=10; // longueur du carré 
    int largeur=10; //largeur du carré
    float value=0; //variable pour la rotation
    float mouseXold=displayWidth/2;
    float mouseYold=displayHeight/2;

    void setup() {

     size(displayWidth, displayHeight);
     background (255);
     smooth();

      myPort = new Serial(this, portName, 9600);
      myPort.bufferUntil(linefeed);
      serial = myPort.readStringUntil(end); // fonction qui lit la chaine de caractères depuis le port série jusqu'à println et ensuite assigne string à notre variable qui appelle serial
      serial = null; // initialisation de serial
     glitchP5 = new GlitchP5(this);
    }


    void draw() {

      while (myPort.available() > 0) { //tant qu'il n'y a pas de données provenant du port on lit l'entrée série
        serial = myPort.readStringUntil(end);
      }
        if (serial != null) {  
          String[] a = split(serial, ','); //on créé un tableau qui définit une chaine séparée par des virgules. 
          println(a[0]); //on affiche la première valeur du tableau
        }

      if((pSensors != null)&&(sensors != null)) { 
        float  rotx = (sensors[0]*10);
        float  roty = (sensors[1]*10);
        float  rotz = (sensors[2]*PI)/180;

    strokeWeight(1);
    noFill(); 
    stroke(random(255),random(255),random(255));
    translate(500,150);
    rectMode(CENTER);


    for(j=0;j<max;j++){
        longueur=longueur+1; 
        largeur=largeur+1; 
        translate(width/2, height/2);
        rotate(value);
        translate(-width/2, -height/2);
        rect(rotx,roty,longueur,largeur); 
        redraw();
        bornexinf=rotxold-10; 
        bornexsup=rotxold+10;
        borneyinf=rotyold-10; 
        borneysup=rotyold+10; 
        if(bornexinf>rotx || rotx>bornexsup || borneyinf>roty || roty>borneysup){
        longueur=5;
        largeur=5;
        }
        rotxold=rotx;
        rotyold=roty;
    }
      }
     glitchP5.run();
    }


    void serialEvent(Serial myPort) {


      String myString = myPort.readStringUntil(linefeed);
      if (myString != null) {
              myString = trim(myString);
              pSensors = sensors;
              sensors = float(split(myString, ','));

                     for (int sensorNum = 0; sensorNum < sensors.length; sensorNum++) {
                     print("Sensor" + sensorNum + ": " + sensors[sensorNum] + "\t");
        }
        println();
      }
    }

    void mousePressed() //===> Will be triggered by the vibration sensor : if =0 do nothing; if =1 glitch; //
    {
     glitchP5.glitch(mouseX, mouseY, 200, 400, 200, 60, 120, 10.0f, 20, 1);
    }

Answers

  • Well, I guess that in line 91 if myString contains only spaces then it is not null but then trim on line 92 will return null? And as so pSensors and sensors will be null too? Have you checked your values with the debugger?

    Yet you say your problem is at line 53, that could mean that sensors is not null but has only one value in it. And that value can be the numeric value of space ' '. Again, I suggest you should first check your input with a print statement or the debugger.

  • edited October 2015

    Thank you for your answer, I tried the debugger, it's not giving me anything! :-<

  • edited October 2015

    I'm starting to think it has to deal with the data coming through the serial port, like to many at once or something.

    Because when I test the gyroscope part only it works, and same for the vibration sensor, and than when I combine them I get this error message.

    Could that make sens? How can I get through that? Does anyone has the great answer i'm looking for? ^:)^

  • are you sure Arduino sends three values or only one? similar to:

    void loop()
    {
       Serial.print(val1);
       Serial.print(",");
       Serial.print(val2);
       Serial.print(",");
       Serial.println(val3);
    }
    
  • edited October 2015

    Hi Camperos thank you so much for helping me out!

    For my gyroscope values i have:

            Serial.print(accel_angle_x, 2);
      Serial.print(F(","));
      Serial.print(accel_angle_y, 2);
      Serial.print(F(","));
      Serial.print(accel_angle_z, 2);
      Serial.print(F(","));
    
      Serial.print(angle_x, 2);
      Serial.print(F(","));
      Serial.print(angle_y, 2);
      Serial.print(F(","));
      Serial.print(angle_z, 2);
      Serial.println(F(""));
    

    And for my vibration sensor :

      int Value1 = analogRead(A0)*3; 
         if(Value1!= 3069)
              {
                valsensor=1; 
              }
            Serial.println(valsensor,DEC);
            valsensor=0; 
            val=analogRead(A0)*3; 
            Serial.println(val); 
          if(val !=3069){
              Serial.println("0000000000000000");
              delay(100);
           }
    

    I've used a tutorial for the gyroscope part and added my code for the vibration sensor.

    Here's a link to the complete code (it's long :/)

  • Answer ✓

    So the gyroscope-part sends 6 values on one line. The vibration-sensor-part sends two values one two lines. So the messages that are send over serial might look kind of like this:

    12, 4, 5, 78, 1, 5
    34
    31
    9, 0, 21, 4, 56, 7
    11
    9
    ...
    

    So when you receive one line in serialEvent(), you store that in the array sensors. Which can have a length of one or six. When you than try to access the second value of the array, while it only has one, you get the error that you posted.

    I would advice that you change your arduino-code, so that it sends all values on one line and all seperated by the same delimiter (comma, space, ..). You can check what kind of messages are send in arduino's serial-monitor.

  • edited November 2015

    Hi Benja, thank you for your answer it helped me clear my code.

    So i've re-written everything and it's starting to work pretty well. I have one problem left: I need to send 0 to Processing when the vibration sensor detects nothing and 1 when it does. So that when it does the glitch is initiated.

    But I must have made a mistake because it only prints me the original values (670, 671...) if you can have a look at my code and tell me where i got wrong.

    Thank you so much!

    ARDUINO

    #include<Wire.h>
    #include<stdio.h> //librairie pour utiliser le printf
    const int MPU=0x68;  // I2C address of the MPU-6050
    int16_t GyX,GyY,GyZ;
    int sensorValue1, sensorValue2, sensorValue3, sensorValue4;
    int valVibrator=0; 
    int val=0; 
    
    void setup(){
      Wire.begin();
      Wire.beginTransmission(MPU);
      Wire.write(0x6B);  // PWR_MGMT_1 register
      Wire.write(0);     // set to zero (wakes up the MPU-6050)
      Wire.endTransmission(true);
      Serial.begin(9600);
    
    }
    void loop(){
      Wire.beginTransmission(MPU);
      Wire.write(0x3B);  // starting with register 0x3B (ACCEL_XOUT_H)
      Wire.endTransmission(false);
      Wire.requestFrom(MPU,6,true);  // request a total of 6 registers
      GyX=Wire.read()<<8|Wire.read();  // 0x43 (GYRO_XOUT_H) & 0x44 (GYRO_XOUT_L)
      GyY=Wire.read()<<8|Wire.read();  // 0x45 (GYRO_YOUT_H) & 0x46 (GYRO_YOUT_L)
      GyZ=Wire.read()<<8|Wire.read();  // 0x47 (GYRO_ZOUT_H) & 0x48 (GYRO_ZOUT_L)
      val=analogRead(A0); 
      Serial.println(val); 
     if(val!=670 || val!=671){
       valVibrator=1;  
     }
      sensorValue1 = GyX/10;  // read sensor in analog input 0
      sensorValue2 = GyY/10;  // read sensor in analog input 1
      sensorValue3 = GyZ;  // read sensor in analog input 2
      sensorValue4 = valVibrator;  // read sensor in analog input 3
      Serial.print(sensorValue1, DEC);  // print sensor 1
      Serial.print(",");                // print ','
      Serial.print(sensorValue2, DEC);  // print sensor 2
      Serial.print(",");                // print ','
      Serial.print(sensorValue3, DEC);  // print sensor 3
      Serial.print(",");                // print ','
      Serial.println(valVibrator, DEC);  // print sensor 4 and newline (println)
      delay(200);   // wait 200ms for next reading
    
      valVibrator=0;}
    

    PROCESSING

            import processing.serial.*;
            import glitchP5.*; //import Glitch P5
            ////codearduino/////////////////////////////
            Serial myPort;
            int linefeed = 10;   // Linefeed in ASCII
            int numSensors = 4;  // we will be expecting for reading data from four sensors
            int sensors[];       // array to read the 4 values
            int pSensors[];      // array to store the previuos reading, usefur for comparing
            // actual reading with the last one
            String portname="/dev/cu.usbmodem1421";
            /////codedessin/////
            GlitchP5 glitchP5; // declare an instance of GlitchP5. only one is needed
            int j=0; //variable d'incrémentation carré dans carré
            int max=1; //nombre d'itération, soit le nb de carrés dans le carré
            int longueur=10; // longueur du carré 
            int largeur=10; //largeur du carré
            float value=0; //variable pour la rotation
            int mouseXold=displayWidth/2;
            int mouseYold=displayHeight/2;
            float bornexinf=0; 
            float bornexsup=0;
            float borneyinf=0; 
            float borneysup=0; 
    
            void setup() {
            size(displayWidth, displayHeight);
             background (255);
             smooth();
             glitchP5 = new GlitchP5(this); // initiate the glitchP5 instance;
              myPort = new Serial(this, portname, 9600);
              // read bytes into a buffer until you get a linefeed (ASCII 10):
              myPort.bufferUntil(linefeed);
            }
    
            void draw() {
            glitchP5.run(); 
            strokeWeight(1);
            noFill(); 
            stroke(random(255),random(255),random(255));
            rectMode(CENTER);
              if ((pSensors != null)&&(sensors != null)) {
    
                for (int i=0; i < numSensors; i++) {
                  float f = sensors[i] - pSensors[i];  // actual - previous value
                  if (f > 0) {
                    println("sensor "+i+" increased by "+f);  // value increased
                  }
                  if (f < 0) {
                    println("sensor "+i+" decreased by "+f);  // value decreased
                  }
                }
                for(j=0;j<max;j++){
               longueur=longueur+1; 
                largeur=largeur+1; 
                translate(width/2, height/2);
                rotate(value);
                translate(-width/2, -height/2);
                rect(sensors[0],sensors[1],longueur,largeur); 
                redraw();
    
                bornexinf=mouseXold-50; 
                bornexsup=mouseXold+50;
                borneyinf=mouseYold-50; 
                borneysup=mouseYold+50; 
                if(bornexinf>sensors[0] || sensors[0]>bornexsup || borneyinf>sensors[1] || sensors[1]>borneysup){
                longueur=5;
                largeur=5;
                }
                mouseXold=sensors[0];
                mouseYold=sensors[1];
    
                if(sensors[3]==1)
                {
                  // trigger a glitch: glitchP5.glitch(  posX,       // 
             //                               posY,       // position on screen(int)
             //          posJitterX,     // 
             //          posJitterY,     // max. position offset(int)
             //          sizeX,       // 
             //          sizeY,       // size (int)
             //          numberOfGlitches,   // number of individual glitches (int)
             //          randomness,     // this is a jitter for size (float)
             //          attack,     // max time (in frames) until indiv. glitch appears (int)
             //          sustain      // max time until it dies off after appearing (int)
             //              );
    
             glitchP5.glitch(sensors[0], sensors[1], 200, 400, 200, 60, 120, 10.0f, 20, 1);
                }
                }
    
                }
              }
    
    
            void serialEvent(Serial myPort) {
              // read the serial buffer:
              String myString = myPort.readStringUntil(linefeed);
    
              // if you got any bytes other than the linefeed:
              if (myString != null) {
    
                myString = trim(myString);
    
                // split the string at the commas
                // and convert the sections into integers:
    
                pSensors = sensors;
                sensors = int(split(myString, ','));
    
                // print out the values you got:
    
                for (int sensorNum = 0; sensorNum < sensors.length; sensorNum++) {
                  print("Sensor " + sensorNum + ":" + sensors[sensorNum] + "\t");
                }
    
                // add a linefeed after all the sensor values are printed:
                println();
    
              }
            }
    
  • edited November 2015

    At a quick glance it looks like you send the value that you read from A0 directly, then do an if-statement that will always be true and assign 1 to valVibrator. So i suppose you were actually sending two lines: one with the current A0-value and another one with 4 values of wich the last is a 1.
    Instead you might want to do it like this:

    val = analogRead(A0);
      if (val < 670 || val > 671) {
        valVibrator = 1;
      } else {
        valVibrator = 1;
      }
    
Sign In or Register to comment.