Arduino Mega 2560 Serial Communication with Processing

Hi. With the Arduino code I have the Processing graphs aren't working as expected.

I am using the grafica library in Processing. So far I am able to run the code in Arduino and then the graphs in Processing pop up. The first serial values come up correctly onto the graphs. However, when the serial values in Arduino change they don't change in Processing. Another thing that occurs is that when I disconnect Arduino, so nothing should be going through the serial port anymore, the Processing graphs continue to run with the first serial values. It is very strange and I can't tell if the problem lies in the Arduino or the Processing code. Any help would be much appreciated! Thanks.

#include <Servo.h>
#include <Wire.h>

float x = 1638.0; //Code for pressure sensor1
float y = 14745.0;
uint16_t val;
float mmHg_per_psi = 51.7;
float mmHg;
int ledPin = 2;    //Code for solenoid valve; Connect to Arduino pin 2
bool state;
unsigned long t;
unsigned long total_time;
unsigned long time_open;
unsigned long time_closed = total_time - time_open;
int heartRate;
int servoPin = 3; //Code for servo motor1  
Servo Servo1; //Create a servo object

//code for the finite state machine

const int realState0 = 0;
const int state0 = 1;
const int state1 = 2;
const int state2 = 3;
const int state3 = 4;

int newState = realState0;

void setup()
{
  Wire.begin(); //Code for pressure sensor
  pinMode(ledPin, OUTPUT); //Code for solenoid valve
  t = millis();
  state = true;
  Servo1.attach(servoPin); //Code for servo motor
  
  Serial.begin(9600);//Setup serial
    
}

void loop()
{
  Wire.requestFrom(0x28, 2); //code for pressure sensor1

  while(Wire.available() == 0);
  
  byte a = Wire.read();
  byte b = Wire.read();
  
  byte status1 = (a & 0xc0) >> 6; //may be able to comment out

  uint16_t val = ((a & 0x3f) << 8) + b;
   
  float psi = (((val - x)*5.0)/(y - x));
  float mmHg = psi * mmHg_per_psi;
  
  Serial.print(mmHg);
  Serial.print(",");
  Serial.print(heartRate);
  Serial.print("\n");
  
    
//Solenoid beats at a certain rate based on pressure sensor1 values
//Servo motor1 goes to a certain angle based on pressure sensor1 values

//static int newState = realState0;
static unsigned long ts;

switch (newState)
{
  case realState0:
    //beginning stage
    Servo1.write(90);

    total_time = 770;
    time_open = 385;
    time_closed = total_time - time_open;
    heartRate = 80;

    newState = state0;

    break;
  
  case state0:
  //normal state 
  if(mmHg > 70.0 && mmHg < 90.0)
  {
    Servo1.write(90);
  
    total_time = 770;
    time_open = 385;
    time_closed = total_time - time_open;
    heartRate = 80;

    ts = millis();
    
    newState = state1;
  }
   break;
  
  case state1:
  //standing up state 
   if(millis() > ts + 30000)
   {
    Servo1.write(100);
  
    total_time = 600;
    time_open = 300;
    time_closed = total_time - time_open;
    heartRate = 100;

    ts = millis();
  
    newState = state2;
    
   }
    break;

   case state2:
   //sitting down state
    if(millis() > ts + 30000)
    {
     Servo1.write(50);
  
     total_time = 1000;
     time_open = 500;
     time_closed = total_time - time_open; 
     heartRate = 60;

     ts = millis();
     
     newState = state3;
     
    }
     break;

    case state3:
     //hemorrhage state
     if(millis() > ts + 30000)
     { 
      Servo1.write(100);
  
      total_time = 500;
      time_open = 250;
      time_closed = total_time - time_open; 
      heartRate = 120;

      newState = state0;
     }
      break;
   default: 
      newState = state0;
}
      
if(state == false && millis() - t > time_closed)
  {
   digitalWrite(ledPin, HIGH);
   state = true;
   t = millis();
  }
  else if (state == true && millis() - t > time_open)
  {
   digitalWrite(ledPin, LOW); 
   state = false;
   t = millis(); 
  }

}
// import require libraries
    import grafica.*;
    import processing.serial.*;// The p5.js sketch will be executed after the library has been loaded

    // create plot instance
    GPlot plot1, plot2;

    //// initialize global variables
    int i = 0; // variable that changes for point calculation
    int points = 1000; // number of points to display at a time
    int totalPoints = 1000; // number of points on x axis
    float noise = 0.1; // added noise
    float period = 0.35;
    long previousMillis = 0;
    int duration = 20;
    String myString = null;
    int xPos = 1;

    
    Serial myPort; // Create object from Serial class

    void setup(){
    
     myPort = new Serial(this, "COM4", 9600);

     myPort.bufferUntil('\n');

     myPort.clear();
     size (900,900);
    
     GPointsArray points1 = new GPointsArray(points);

    // calculate initial display points
    for (i = 0; i < points; i++) 
    {
      points1.add(i,0);
    }

    // Create the plot 1
    plot1 = new GPlot(this);
    plot1.setPos(25, 25); // set the position of to left corner of plot
    plot1.setDim(750, 300); // set plot size

    // Set the plot limits (this will fix them)
    plot1.setXLim(0, totalPoints); // set x limits
    plot1.setYLim(0, 250); // set y limits

    // Set the plot title and the axis labels
    plot1.setTitleText("Pressure"); // set plot title
    plot1.getXAxis().setAxisLabelText("Time"); // set x axis label
    plot1.getYAxis().setAxisLabelText("Pressure mmHg"); // set y axis label

    // Add the two set of points to the plot
    plot1.setPoints(points1);
    
      // Create the plot 2
    plot2 = new GPlot(this);
    plot2.setPos(25, 450); // set the position of to left corner of plot
    plot2.setDim(750, 300); // set plot size

    // Set the plot limits (this will fix them)
    plot2.setXLim(0, totalPoints); // set x limits
    plot2.setYLim(0, 125); // set y limits

    // Set the plot title and the axis labels
    plot2.setTitleText("Heart Rate"); // set plot title
    plot2.getXAxis().setAxisLabelText("Time"); // set x axis label
    plot2.getYAxis().setAxisLabelText("Beats per Minute"); // set y axis label

    // Add the two set of points to the plot
    plot2.setPoints(points1);
   

    }

    void draw() {
    // set window background
    background(150);

    // draw plot 1
    plot1.beginDraw();
    plot1.drawBackground();
    plot1.drawBox();
    plot1.drawXAxis();
    plot1.drawYAxis();
    plot1.drawTopAxis();
    plot1.drawRightAxis();
    plot1.drawTitle();
    plot1.getMainLayer().drawPoints();
    plot1.endDraw();
    
     // draw plot 2
    plot2.beginDraw();
    plot2.drawBackground();
    plot2.drawBox();
    plot2.drawXAxis();
    plot2.drawYAxis();
    plot2.drawTopAxis();
    plot2.drawRightAxis();
    plot2.drawTitle();
    plot2.getMainLayer().drawPoints();
    plot2.endDraw();
   

    // check if i has exceeded the plot size
    if (i > totalPoints)
    {
      i=0; // reset to zero if it has
    }

    // get new value from serial port
    if ( millis() > previousMillis + duration) { // If data is available,
      myPort.write(0);
      delay(500);
        
      while (myPort.available() < 0){};
         String inString = myPort.readStringUntil('\n'); // get the ASCII string:
        if (inString != null) {
          inString = trim(inString); //Split the string value dot as delimiter
          float[] nums=float(split(inString,","));
          println("First sensor value="+nums[0]);  //nums[1]=second sensor value
          println("Second Sensor value="+nums[1]); // convert to an int and map to the screen height:
         
    // Add the point at the end of the array
      i++;
      plot1.addPoint(i,nums[0]);
      plot2.addPoint(i,nums[1]);
     


    // Remove the first point
      plot1.removePoint(0);
      plot2.removePoint(0);

    }
  }
 }

Do something simple.

Write a sketch for the Arduino that sends 1, 2, 3 to Processing.
Once you are able to read that reliably then you can do other things.

The problems with newbies is that you don't the basics.

Ok. I did the simpler code, and I got both graphs to work. I found that having the variable "mmHg" outside of the switch case never made it to the processing graph. I don't know how to solve this problem because "mmHg" is getting updated values from a pressure sensor, and I don't know how I would incorporate it into the switch case to send it to Processing. Here is the simplified Arduino code I wrote:

#include <Servo.h>
#include <Wire.h>

int heartRate;
int mmHg;

//code for the finite state machine

const int realState0 = 0;
const int state0 = 1;
const int state1 = 2;
const int state2 = 3;
const int state3 = 4;

int newState = realState0;

void setup()
{
  
  Serial.begin(9600);//Setup serial
    
}

void loop()
{


 
switch (newState)
{
  case realState0:
   
    heartRate = 80;
    mmHg = 20;
    newState = state0;
     
    break;
  
  case state0:
  //normal state 
 
    heartRate = 50;
    mmHg = 10;
    newState = state1;
   break;
  
  case state1:
   
    heartRate = 100;
    mmHg = 9;
    newState = state2;
    
    break;

   case state2:
   //sitting down state
  
     heartRate = 60;
     mmHg = 8;
     newState = state3;
     
     break;

    case state3:
     //hemorrhage state
    
      heartRate = 120;
      mmHg = 7;
      newState = state0;
      break;
      
   default: 
      newState = state0;
}
  
  Serial.print(mmHg);
  Serial.print(",");
  Serial.print(heartRate);
  Serial.print("\n");
}

When I left "mmHg" out of the switch statement and had it reading from my pressure sensor, as I have shown in my original code, the sensor values did not change in Processing. The "heartRate" values did change in the Processing graph when I had them written as I do in the simplified code however. Basically, before I got to the super simplified version, I first kept the pressure sensor code with it. This is how I came to the conclusion that the "mmHg" variable isn't available in the switch statement.

Right! I am not sure how to incorporate the "mmHg" variable into the switch statement if it is getting new sensor values in real time.

So in my original code, as written, the Processing value that was received from the sensor was the first value. For example if my system pressure was 80 mmHG it read that. If I changed the pressure to 70 mmHg, the Processing value did not change but kept reading 80 mmHg.

However, in the Arduino serial monitor the sensor values change as the system pressure changes.

When I tried to simplify my code to try and find the problem, the only way I was able to get the two graphs to work was by giving specific values to mmHg, and not having them be updated in real time. I need them to be able to be updated in real time.

Does this make it more clear, or do I need to clarify further? I may be missing where the confusion is it.

Thank you for your time!

Well I was just thinking that sense I got the values in Processing to update correctly with the simplified code that I might need to just figure out how to add the real time updated "mmHg" value into the switch statement. I may just be looking at it the wrong way. I'm not really sure.

The local mmHg. Sorry! I ran the simplified version with mmHg as a float variable and the Processing graphs still worked. I think you may be right that the problem is in the processing code. The Processing code I used is the second set of code in my first post.

mmpallan:
I think you may be right that the problem is in the processing code. The Processing code I used is the second set of code in my first post.

Maybe first simply use serial monitor to display the values. Or a real terminal program like putty or realterm and write the results to file so you can analyse. Once you're 100% sure that the Arduino code is correct, you can debug the processing code.

Thanks for the help everyone!

I found a solution that gets both the graphs to work with a few changes in my original Arduino code! I had to add a for statement with if and else if statements with ranges using the variable mmHg, and then having the heartRate variable be changed in the if and else if statements instead of in the switch case. Don't know if this is the best way to do it, but it's the only solution I have found!