processing to arduino

Hello everyone,

I am making a little program with processing and arduino. What I want to do is to click on a button in the processing program and then send a value to the arduino code, when it gets the value, I want it to move a servomotor forward and backward until I click on another button in the processing code.

However, I am just sending the value just once to the arduino, hence, it only moves the servo forward and I need to click on the button again to go back to the initial position.

I have tried to do while loop to keep sending the same value if I click the button but then I can't get out of the loop.

This is my relevant arduino code (I've got more buttons to make the servo move with a potentiometer and a FSR but if I'm capable to make it work with one, I'll mmake it work with the others) :

void loop ()
{
  if(Serial.available()){
     val= Serial.read();
     switch(val){
      //-------------------------- Close Mode----------------------//
      case 0:
         if(val == 0){
            digitalWrite(ledPot, LOW);
            digitalWrite(ledCPM, LOW);
            digitalWrite(ledFSR, LOW);         
        }
        break;
      //--------------------------CPM Mode----------------------//
      case 1: 
           if(val == 1){
            cpmMovement();
            digitalWrite(ledCPM, HIGH);
            digitalWrite(ledPot, LOW);
            digitalWrite(ledFSR,LOW);
         
            }
            break; 
      //--------------------------POT Mode----------------------//
      case 2:
          if(val == 2){
            digitalWrite(ledPot, HIGH);
            digitalWrite(ledCPM, LOW);
            digitalWrite(ledFSR,LOW);
            potMovement();
          }
          break;
      //--------------------------FSR Mode----------------------//
      case 3:
          if(val == 3){
            digitalWrite(ledPot, LOW);
            digitalWrite(ledCPM, LOW);
            digitalWrite(ledFSR,HIGH);
            fsrMovement();
            
        }
        break;
      //---------------------Calibration Mode-----------------------//
      case 4:
          if(val == 4){
            digitalWrite(ledPot,HIGH);
            digitalWrite(ledCPM,HIGH);
            digitalWrite(ledFSR,HIGH);
            
        }
        break;
}

And here's my relevant processing code:

void update(int x, int y) {  //Update postion of mouse



  if ( pressedButtonCPM(cpmButtonX, cpmButtonY, butWidth, butHeight ) ) {
    pressedCPMButton = true;
    pressedPOTButton = false;
    pressedFSRButton = false;
    pressedCALButton = false;
    pressedBACKButton = false;
    pressedSTARTCALButton = false;
    //myPort.write(1);
    //println(1);
  } 
}

void mousePressed() {
  println("Coordinates: "  + mouseX + "," + mouseY);
  if (pressedCPMButton && currentColorCPM==butColor) { //Changing color CPM to pressed button color
    currentColorCPM = butpreColor;
    currentColorPOT = butColor;
    currentColorFSR = butColor;
    currentColorCAL = butColor;
    myPort.write(1);   //Send 1 to port
    println(1);
  } else if (pressedCPMButton && currentColorCPM==butpreColor) {
    currentColorCPM = butColor;
    currentColorPOT = butColor;
    currentColorFSR = butColor;
    currentColorCAL = butColor;
    myPort.write(0);   //Send 1 to port
    println(0);
  }
 
 
 
  }

You want to do something on the Arduino with val, regardless of whether or not val changes on any given pass through loop(). Get the code that deals with using val OUT of the if(Serial.available()) block.

By the way, Serial.available() returns the number of bytes available to be read, NOT true or false. Don't use it as though it returned true or false.

Thank you! It worked :slight_smile:

You may find some useful stuff in Serial Input Basics

...R

Thank for both of your answers!

Now, I am trying to record the maximum value of the force sensitive resistor for 5 seconds when I press a button on the processing program however I have only been able to get the first value on the serial monitor.

I have tried without pressing the button so when I open the program it starts recording the values as it is supposed to work. So I can see in the serial monitor, the max value and the actual value for the 5 seconds

Here's my arduino code:

void loop (){
  if (Serial.available()) {
    val = Serial.read();
  }

  switch (val) {
    //-------------------------- Close Modes----------------------//
    case 0:
      if (val == 0) {
        digitalWrite(ledPot, LOW);
        digitalWrite(ledCPM, LOW);
        digitalWrite(ledFSR, LOW);
      }
      break;
    //--------------------------CPM Mode----------------------//
    case 1:
      if (val == 1) {
        cpmMovement();
      }
      break;
    //--------------------------POT Mode----------------------//
    case 2:
      if (val == 2) {
        potMovement();
      }
      break;
    //--------------------------FSR Mode----------------------//
    case 3:
      if (val == 3) {
        fsrMovement();

      }
      break;
    //---------------------Calibration Mode-----------------------//
    case 4:
      if (val == 4) {
        digitalWrite(ledPot, HIGH);
        digitalWrite(ledCPM, HIGH);
        digitalWrite(ledFSR, HIGH);

      }
      break;
    //-----------------Calibration Started---------------------//
    case 5:
     if (val == 5) {
        sendMaxValue();
     }
     break; 
  }
}

void sendMaxValue(){
  maxforce = analogRead(FSR) / 4;
  unsigned long currentMillis = millis();
  long prevMillis = 0;
  long calibrationTime = 5000;
  long maxReadingTime = 5010;

  if (currentMillis - prevMillis <= calibrationTime) {
    previousMillis = currentMillis;
    if (maxforce > maxReading) maxReading = maxforce;
    Serial.print(maxReading);         
    Serial.print('\t');         
    Serial.println(maxforce);
  }

  if (currentMillis - previousMillis >= interval && currentMillis - previousMillis <= maxReadingTime){
    maxforce = maxReading;
    
    Serial.print(maxReading);
    Serial.print('\t');         
    Serial.println(maxforce);
  }
  
}

I am pretty sure there's a better method to stop recording the values after 5 seconds but I don't know it :stuck_out_tongue:

And here's the relevant code for processing:

void drawScreenCalibration() {
  update(mouseX, mouseY);
  
  background(0, 0, 0);
  noStroke();
  
  //Back Button, goes back to the main menu
  fill(butColor);
  rect(backButtonX, backButtonY, backButWidth, backButHeight, 10); //pixelX, pixelY, width, height of Back button
  
  //Calibration Button
  fill(butColor);
  rect(startCalButtonX, startCalButtonY, startCalButWidth, startCalButHeight, 10); //pixelX, pixelY, width, height of Start calibration button
  fill(255, 255, 255);
  textSize(20);
  textAlign(CENTER);
  text("Start CALIBRATION", 400, 307);  
}

void mousePressed() {
  println("Coordinates: "  + mouseX + "," + mouseY);

  if (pressedSTARTCALButton) {
    myPort.write(5);                                    //Send 5 to port so sendMaxValue() function can start
    if(myPort.available() > 0){
      valforce = myPort.readStringUntil('\n');
      println(valforce);
    }
  }
}

However, using that code is just recording the first value. And using the next code it works as I wanted to work

void draw() {
  if(myPort.available() > 0){
  } 
  myPort.write(5);
    switch(currentScreen) {
    case 0: 
     drawMainMenu(); 
     break;
    case 1: 
     drawScreenCalibration(); 
     break;
    default: 
     drawMainMenu(); 
     break;
    }
  
}

void drawMainMenu() {
  background(0, 0, 0);

  valforce = myPort.readStringUntil('\n');
  println(valforce);

  
}
  switch (val) {
    //-------------------------- Close Modes----------------------//
    case 0:
      if (val == 0) {

You don't understand what switch does, do you?

In case 0, of course val is going to be 0. In case 1, of course it is going to be 1.

Where do you read the FSR? What, exactly, are you sending TO the Arduino?

PaulS:
You don't understand what switch does, do you?

In case 0, of course val is going to be 0. In case 1, of course it is going to be 1.

I know, but somehow it didn't work well if I didn't write the if statements, I have deleted them now and it's working fine. It was probably something else. Thanks!

PaulS:
Where do you read the FSR? What, exactly, are you sending TO the Arduino?

I'm reading the FSR in the sendMaxValue() function showed in the arduino code I posted. And to the arduino I am sending the value 5 when I press the button at the processing program so the arduino gets val = 5 and starts printing the maximum value and actual value of the FSR on the serial monitor.

I have changed the processing code a bit and now it kind of seems to work. However if more than 5 seconds passes before I clicked on the button, I get null. And also,the first time I click on the button I also get null but if I press it a second time it starts printing the FSR values

This is what I have changed:

if (pressedSTARTCALButton) {
    if(myPort.available() > 0){
    }
    myPort.write(5);     //Send 5 to port
    valforce = myPort.readString();
    println(valforce);
  }
}

Please, bear with me as I am still quite new and English is not first language, thank you again!

I'm reading the FSR in the sendMaxValue() function

ONCE. So, the only value is the minimum value, the maximum value, the median value, and the average value. Is that what you want? If so, what is the problem?

EDIT: I just realized I can't use millis() because millis counts the time since the arduino it's restarted and that's probably why I'm getting null if I press the button after 5 seconds. I'll try to find another way to make that function run for 5 seconds. If I can't, I'll look for help again :stuck_out_tongue: Thank you!

No, I'm reading the FSR for 5 seconds and then it stops reading. And that it's working fine.

void sendMaxValue(){
  force = analogRead(FSR) / 4;
  unsigned long currentMillis = millis();
  long prevMillis = 0;
  long calibrationTime = 5000;
  long maxReadingTime = 5010;

  if (currentMillis - prevMillis <= calibrationTime) {           //if currentmillis is less than 5 seconds, print maxvalue and actual value
    prevMillis = currentMillis;
    if (force > maxReading) maxReading = force;
    Serial.print(maxReading);         
    Serial.print('\t');         
    Serial.println(force);
  }
}

And I'm sending those values to the serial monitor inside processing. However it is not working as it is supposed to work.

What I want is to press a button on a processing program, the processing code sends a value to the arduino, then the arduino code starts running the sendMaxValue function which prints the values on the serial monitor and then I want to put on the processing window the maximum value of the FSR for those 5 seconds.

What I'm getting is when I press the button for the first time I get null in the serial monitor and when I press it again I see the values but they are not the actual values of the FSR and if I start the program and press the button after more than 5 second, all I get is null.

Thanks

rojascan:
EDIT: I just realized I can't use millis() because millis counts the time since the arduino it's restarted

What's that got to do with anything?

You can use your kitchen clock to time the boiling of an egg even though the clock counts from midnight!

Just use the difference between the value of millis() then and now. See Several Things at a Time

...R

No, I'm reading the FSR for 5 seconds and then it stops reading.

Where? Show me the block of code that does that.

PaulS:
Where? Show me the block of code that does that.

It's inside the function sendMaxValue. The first if statement

void sendMaxValue(){
  force = analogRead(FSR) / 4;
  unsigned long currentMillis = millis();
  long prevMillis = 0;
  long calibrationTime = 5000;
  long maxReadingTime = 5010;

  if (currentMillis - prevMillis <= calibrationTime) {           //if currentmillis is less than 5 seconds, print maxvalue and actual value
    prevMillis = currentMillis;
    if (force > maxReading) maxReading = force;
    Serial.print(maxReading);         
    Serial.print('\t');         
    Serial.println(force);
  }
}

It's inside the function sendMaxValue. The first if statement

The first if statement does NOT cause the function to loop until 5 seconds has elapsed.

The inclusion of prevMillis in that statement, after you assigned it a value of 0, is useless. What the if statement then tests is whether the Arduino has been running for more than 5 seconds. If it has, the maxReading and force values are sent. Otherwise, nothing is sent.

PaulS:
The first if statement does NOT cause the function to loop until 5 seconds has elapsed.

It does, since it's checking if currentmillis - prevmillis is less than 5 seconds, but you are absolutely right! I'm not doing anything with prevmillis there. I'm really sorry for my incompetence.

Let's simplify the problem a bit. I want to record the max value of the FSR for 5 seconds with a push button. So I create a boolean to check if the push button has been pushed. If it has then it loops for 5 seconds and when it finishes the boolean comes back to false. And therefore I would be able to push the button and start recording.

However I don't know how to get it done. How do I check the time for 5 seconds and then if I push again make it work again? I'm pretty sure there might be a simple solution to this and I am being quite dumb.

However I don't know how to get it done. How do I check the time for 5 seconds and then if I push again make it work again? I'm pretty sure there might be a simple solution to this and I am being quite dumb.

   int maxState = digitalRead(maxPin); // Read the pin that should trigger 5 seconds of reading
   if(maxState == LOW) // Assumes that you use a pullup resistor so LOW means pressed
   {
      unsigned long startTime = millis();
      while(millis() - startTime < 5000) // Iterate for 5 seconds
      {
         int force = analogRead(fsrPin);
         if(force > maxForce)
            maxForce = force;
      }
      Serial.print("After 5 seconds, the maximum reading was: ");
      Serial.println(maxForce);
   }

Thank you! I really appreciate your help!