Communicatieprobleem tussen Arduino en Processing

Beste leden,

Ik probeer enkele servo's aan te sturen gekoppeld aan een Arduino UNO vanuit processing met behulp van
de controlP5 bibliotheek. Dit is een Graphical User Interface. (zie processing GUI, controlP5).
De 5 servo's kan ik zonder problemen besturen vanuit processing met behulp van sliders (en in de arduino
code case 1 tot case 5). De bedoeling is dat ik de servo's vanuit processing ook aan en uit kan zetten met
behulp van de functies attach() en detach() die ik gebruik in de arduino code.
Het aanzetten van de servo's lukt altijd zonder enig probleem (dit is case 6 in de arduino code, en in processing
vanuit de functie void ON_OFF(boolean btnEnabled)).
Het uitzetten m.b.v. de detach() functie in de arduino code vanuit processing lukt nooit (in de arduino
code is dat case 7 en ook via de zelfde functie in processing).

Heeft er iemand enig idee wat er fout is?

De arduino code ziet er als volgt uit:

#include <Servo.h>

Servo servo_robot_1;   
Servo servo_robot_2;  
Servo servo_robot_3;   
Servo servo_grijper_rotatie;   
Servo servo_grijper_hand;   

int Servo_1_Pin = 9;    
int Servo_2_Pin = 10;   
int Servo_3_Pin = 11;   
int Servo_4_Pin = 5;   
int Servo_5_Pin = 6;   

int minPulse = 544;    
int maxPulse = 2400;  

int t;  
int pos;
int servo;
int startbyte;
int userInput[5];   

boolean enableServos = false;


void setup(){
  Serial.begin(19200);   
}

// Oneindige loop
void loop(){
  if (Serial.available() > 3){
    startbyte = Serial.read();
    if (startbyte == 255){
      for (t = 0; t<2; t++){
        userInput[t] = Serial.read();
      }
      servo = userInput[0];
      pos = userInput[1];
      if (pos == 255){
        servo = 255;
      }
      switch(servo){
        case 1:
          servo_robot_1.write(pos + 12);   // Plus de offset van de servo's en de software    
          break;
        case 2:
          servo_robot_2.write(pos + 16);
          break;
        case 3:
          servo_robot_3.write(pos + 22);
          break;
        case 4:
          servo_grijper_rotatie.write(pos);
          break;
        case 5:
          servo_grijper_hand.write(pos);
          break;
        case 6:
          if (pos == 180){
            attach_Servos();
          }
          break;
        case 7: 
          if (pos == 0){
            detach_Servos();
          }
          break;
      }
    }   
  }
}

void attach_Servos(){
  servo_robot_1.attach(Servo_1_Pin, minPulse, maxPulse);   
  servo_robot_2.attach(Servo_2_Pin, minPulse, maxPulse);   
  servo_robot_3.attach(Servo_3_Pin, minPulse, maxPulse);   
  
  servo_grijper_rotatie.attach(Servo_4_Pin, minPulse, maxPulse);   
  servo_grijper_hand.attach(Servo_5_Pin, minPulse, maxPulse);   
  
  enableServos = true;
}

void detach_Servos(){
  servo_delta_robot_1.detach();
  servo_delta_robot_2.detach();
  servo_delta_robot_3.detach();
  
  servo_grijper_rotatie.detach();
  servo_grijper_hand.detach();
  
  enableServos = false;
}

Een deel van de processing code:

void sendSerialData() {
  if (servosEnabled) {
    sendMove(1, serialAngle0 = (int)map(dRobot.servoAngles[0], radians(-90), radians(90), 0, 180));
    sendMove(2, serialAngle1 = (int)map(dRobot.servoAngles[1], radians(-90), radians(90), 0, 180));
    sendMove(3, serialAngle2 = (int)map(dRobot.servoAngles[2], radians(-90), radians(90), 0, 180));
    sendMove(4, gripRot);
    sendMove(5, gripWidth);
    }
}


void ON_OFF(boolean btnEnabled) {
  if (btnEnabled==true) {
    sendMove(6, 180);
    servosEnabled = true;
    println("Servos enabled");
  } 
  else if (btnEnabled==false) {
    sendMove(7, 0);
    servosEnabled = false;
    println("Servos not enabled");
  }
}


void sendMove(int servo, int val) {
  myPort.write(255);
  myPort.write(servo);
  myPort.write(val);
}

Hoi.
Bereikt je servo ooit die waarde nul ?
Want das de secondaire voorwaarde naast case 7.
Als dit niet het geval is, moet je dat oplossen.
Dat kun je doen door 'm naar nul te forceren, of te controleren of je onder een bepaalde waarde bent uitgekomen in plaats van op een absolute waarde te controleren.

Als je aan het debuggen bent, is het altijd goed een vorm van terugkoppeling te hebben zodat je kunt zien wat er gebeurt.
Aangezien je al een seriële verbinding hebt staan met processing, is het een misschien wel een goed idee om met een LCD te werken hiervoor.

Het is moeilijk om aan het debuggen te slaan vanwege de seriële verbinding met processing.
Een LCD display heb ik niet direct bij de hand maar dit bracht mij wel op het idee om een LED
te sturen. In case 6 gaat de LED aan en in case 7 zou deze moeten uitgaan wat niet gebeurt.
Ik heb de secundaire voorwaarde uit de code gehaald maar steeds hetzelfde probleem.
In de programmatie kant processing kan ik wel zien in het textvenster onderaan dat de functie
"void ON_OFF(boolean btnEnabled)" correct wordt doorlopen via println("Servos not enabled").
De data zou dus wel moeten toekomen in de arduino programmatie. Ik begrijp dus niet waarom
de waarde nul niet toekomt in case 7 (andere waarden ook al geprobeerd).

vesper:
Ik heb de secundaire voorwaarde uit de code gehaald maar steeds hetzelfde probleem.

Dus je hebt nu dit stukje:

        case 7: 
            detach_Servos();
          break;

?

Als dat niet werkt, en je LED (die je daar dan dus nog ergens tussen hebt staan) niet uitgaat, dan zou je dus nooit deze waarde 7 bereiken.

Dat klopt.

        case 6:
          if (pos == 254){
            digitalWrite(debugLed, HIGH);
            attach_Servos();
          }
          break;
        case 7: 
          digitalWrite(debugLed, LOW);
          detach_Servos();
          }
          break;

Het lijkt of hij case 7 niet bereikt want de LED blijft branden maar heb geen idee wat de reden is. De programmatie in processing is ongewijzigd gebleven. Case 1 tot 6 werkt daarentegen wel perfect.

Dan moet je probleem in processing zitten.
Ik ken processing verder niet dus zeker ook de kneepjes niet.

Maar hier zie ik wel een aandachtspuntje:

void ON_OFF(boolean btnEnabled) {
  if (btnEnabled==true) {
    sendMove(6, 180);
    servosEnabled = true;
    println("Servos enabled");
  } 
  else if (btnEnabled==false) {
    sendMove(7, 0);
    servosEnabled = false;
    println("Servos not enabled");
  }
}

Want je kijkt hier of btnEnabled waar is (waar betekent anders als 0).
In dat geval doe je iets, en omdat je daar niet over klaagt, neem ik aan dat dat werkt.
Als bij die controle is gebleken dat btnEnabled niet anders als nul was (dit is het woordje "else"), kijk je of ie dan misschien wel nul was (in "if (btnEnabled==false) ).
Das dubbelop en daarom onnodig.
Dus die tweede if kun je gewoon eruit slopen en daarmee je code wat optimaliseren.

Sterker nog, je kunt ook de ==true eruit slopen, zodat je alleen dit krijgt in die regel:

  if (btnEnabled) {

Dat moet net zo goed werken, maar of dat de schoonheidsprijs zal winnen is dan maar de vraag.

Verder raad ik je aan om in je println, ook de waarde van die btnEnabled te verzenden (bij wijze van debugging).
Dat kan je verraden waarom je die 7 nooit verzendt.