Braccio robotico & matematica (trigonometria dei cerchi)

questa te la rubiamo per le citazioni, grazie

il problema esisteva già al post 15 del 14 settembre
6 settimane abbondanti non sono bastate a focalizzarlo?

Qui il problema della divisione che da 0 non c'è, non ci sono divisioni...

Ho inoltre scartato gli altri sketch e ora mi baso solo su questo:

void movimento(int x, int y){
  for(int a = 0; a < 180; a++){
    if(currentAngle[0] < x && currentAngle[1] < y){
      currentAngle[0]++;
      currentAngle[1]++;
    }else if(currentAngle[0] > x && currentAngle[1] > y){
      currentAngle[0]--;
      currentAngle[1]--;
    }else if(currentAngle[0] < x && currentAngle[1] > y){
      currentAngle[0]++;
      currentAngle[1]--;
    }else if(currentAngle[0] > x && currentAngle[1] < y){
      currentAngle[0]--;
      currentAngle[1]++;
    }else if(currentAngle[0] == x && currentAngle[1] == y){
      a = 180;
    }
    base.write(currentAngle[0]);
    giunto.write(currentAngle[1]);
    delay(25);
    Serial.print(currentAngle[0]);
    Serial.print("    ");
    Serial.println(currentAngle[1]);
  }

Che però funziona per metà. Nel senso che x va bene, mentre y va ad angoli sballati, come mai?

E poi come mi posso liberare degli if se un angolo deve aumentare e l'altro deve diminuire?

per salvor hardin
prendete pure, grazie per la stima

per OP

prendi esempio d questo:

void movimento(int x, int y) {
bool prosegui = 1:
  while (prosegui) {
    prosegui = 0;
    if (currentAngle[0] < x) {
      base.write(++ currentAngle[0]);
      prosegui = 1;
    }
    if (currentAngle[0] > x) {
      base.write(-- currentAngle[0]);
      prosegui = 1;
    }
    if (currentAngle[1] < y) {
      giunto.write(++ currentAngle[1]);
      prosegui = 1;
    }
    if (currentAngle[1] > y) {
      giunto.write(-- currentAngle[1]);
      prosegui = 1;
    }
    delay(25);
  }
}

che dovrebbe risolvere un paio dei problemi
in particolare il fatto di fare 180 pause anche quando magarideve fare solo pochi gradi un solo asse

vedi se ti serve come indizio

Il ptoblema della divisione che da zero è che tu in un mese e mezzo non lo hai ancora capito

Se e quando supererai questo scoglio forse arriverai in porto

Si, lo ho capito (o almeno credo): se immagazzino in una variabile (non float) un valore inferiore a 1 sarà considerato zero. Non è così?

Si vabbé

Tanti auguri

1 Like

Ho capito l'erroreee,
in pratica il primo dei due angoli che arriva all'angolo desiderato blocca il tutto, quindi devo trovare il modo di bloccare questa cosa, giusto @C1P8?
Ora provo a serpararli e fare degli if di una sola condizione

Ci sono riuscito!!!

#include <Servo.h>
Servo base;
Servo giunto;
Servo SAR;
int currentAngle[2];
void setup() {
  Serial.begin(9600);
  SAR.attach(3);
  base.attach(2);
  giunto.attach(4);
  base.write(60);
  giunto.write(60);
  currentAngle[0] = 60;
  currentAngle[1] = 60;
}

void loop() {
  movimento(90, 50);
  delay(500);
  movimento(50, 90);
  delay(500);
}


void movimento(int x, int y){
  for(int a = 0; a < 180; a++){
    if(currentAngle[0] < x){
      currentAngle[0]++;
    }else if(currentAngle[0] > x){
      currentAngle[0]--;
    }
    if(currentAngle[1] < y){
      currentAngle[1]++;
    }else if(currentAngle[1] > y){
      currentAngle[1]--;
    }
    if(currentAngle[0] == x && currentAngle[1] == y){
      a = 180;
    }
    base.write(currentAngle[0]);
    giunto.write(currentAngle[1]);
    delay(25);
    Serial.print(currentAngle[0]);
    Serial.print("    ");
    Serial.println(currentAngle[1]);
  }
}

Slegando le due condizioni ora funziona tutto

Direi che abbiamo finito :slight_smile:

/*
MACCHINA A STATI:
  stato = 0:    lettura e movimento su base di angoli settati manualmente
  stato = 1:    aggiornamento angolo in values[INDEX][1]
  stato = 2:    movimento in base a values[][]
  Premere il pulsante 1 per iniziare la registrazione delle posizioni e registrare quelle correnti
  Premere il pulsante 2 per iniziare la riproduzione delle posizioni memorizzate

*/



#define Pulsante1 24
#define Pulsante2 25
#define SUbase 22
#define GIUbase 23
#define SUgiunto 26
#define GIUgiunto 27
#include <Servo.h>
Servo base;
Servo giunto;

int values[10][2];/* = {
  55, 78, 130, 18, 90, 78, 14, 69, 87, 53,
  130, 50, 60, 15, 30, 90, 65, 74, 55, 33       
};*/
byte INDEX = 11;
int angle[2] = {60, 30};
int currentAngle[2];
unsigned long prevT[2];
unsigned long tempo;
int intervallo = 50;
int intervalluzzo = 500;
byte stato = 0;
bool possibilities = 1;



void setup() {
  Serial.begin(9600);
  currentAngle[0] = 60;
  currentAngle[1] = 30;
  base.attach(2);
  base.write(60);
  giunto.attach(4);
  giunto.write(30);
  angle[0] = 60;
  angle[1] = 30;
}

void loop(){
  switch(stato){
    case 0:
      letturaAngolo();
      movimento(angle[0], angle[1]); 
    break;
    case 1:
      letturaAngolo();
      movimento(angle[0], angle[1]);
      if(digitalRead(Pulsante1) == HIGH){
        values[INDEX][0] = angle[0];
        values[INDEX][1] = angle[1];
        Serial.print("pos base:");
        Serial.print(values[INDEX][0]);
        Serial.print("; pos giunto:");
        Serial.print(values[INDEX][1]);
        Serial.println(";");
        INDEX++;
        delay(500);
      }
    break;
    case 2:
      Serial.println("Inizio movimenti programmati");
      for(int i = 0; i < 10; i++){
        movimento(values[i][0], values[i][1]);
      }
      stato = 0;
    break;
  }

  if(digitalRead(Pulsante1) == HIGH && INDEX == 11){
    stato = 1;
    possibilities = false;
    INDEX = 0;
    Serial.println("lettura iniziata");
    delay(1000);
  }
  if(digitalRead(Pulsante2) == HIGH && possibilities == true){
    stato = 2;
  }
  if(INDEX == 10){
    if(millis() > intervalluzzo + tempo){
      Serial.println("lettura finita, premere pulsante 2");
      tempo = millis();
    }
    possibilities = true;
    stato = 0;
    INDEX = 11;
  }
}

void letturaAngolo(){
  if(digitalRead(SUbase) == HIGH && prevT + intervallo < millis() && angle[0] >= 0 && angle[0] < 180){
    angle[0]++;
    prevT[0] = millis();
  }
  if(digitalRead(GIUbase) == HIGH && prevT + intervallo < millis()&& angle[0] <= 180 && angle[0] > 1){
    angle[0]--;
    prevT[0] = millis();
  }  
  if(digitalRead(SUgiunto) == HIGH && prevT[1] + intervallo < millis() && angle[1] >= 0 && angle[1] < 180){
    angle[1]++;
    prevT[1] = millis();
  }
  if(digitalRead(GIUgiunto) == HIGH && prevT[1] + intervallo < millis()&& angle[1] <= 180 && angle[1] > 1){
    angle[1]--;
    prevT[1] = millis();
  }
}

void movimento(int x, int y){
  for(int a = 0; a < 180; a++){
    if(currentAngle[0] < x){
      currentAngle[0]++;
    }else if(currentAngle[0] > x){
      currentAngle[0]--;
    }
    if(currentAngle[1] < y){
      currentAngle[1]++;
    }else if(currentAngle[1] > y){
      currentAngle[1]--;
    }
    if(currentAngle[0] == x && currentAngle[1] == y){
      a = 180;
    }
    base.write(currentAngle[0]);
    giunto.write(currentAngle[1]);
    delay(25);
  }
}

Se si può ottimizzare lo sketch sono aperto a tutte le possibili ottimizzazioni :slight_smile:

Buonasera a tutti,
Ho aggiunto anche "il polso e la mano" allo sketch (basta aggiungere due valori negli array e piccoli pezzi di codice:

/*
MACCHINA A STATI:
  stato = 0:    lettura e movimento su base di angoli settati manualmente
  stato = 1:    aggiornamento angolo in values[INDEX][1]
  stato = 2:    movimento in base a values[][]
  Premere il pulsante 1 per iniziare la registrazione delle posizioni e registrare quelle correnti
  Premere il pulsante 2 per iniziare la riproduzione delle posizioni memorizzate


  Base: 2
  Gomito: 4
  Polso: 3
  Mano: 5
*/



#define Pulsante1 22
#define Pulsante2 23
#define SUbase 24
#define GIUbase 25
#define SUgiunto 26
#define GIUgiunto 27
#define SUpolso 28
#define GIUpolso 29
#define APRImano 30
#define CHIUDImano 31
#include <Servo.h>
Servo base;
Servo giunto;
Servo polso;
Servo mano;

int values[10][4];/* = {
  55, 78, 130, 18, 90, 78, 14, 69, 87, 53,
  130, 50, 60, 15, 30, 90, 65, 74, 55, 33       
};*/
byte INDEX = 11;
int angle[4] = {60, 30, 90, 30};
int currentAngle[4];
unsigned long prevT[4];
unsigned long tempo;
int intervallo = 50;
int intervalluzzo = 500;
byte stato = 0;
bool possibilities = 1;



void setup() {
  Serial.begin(9600);
  currentAngle[0] = 60;
  currentAngle[1] = 30;
  currentAngle[2] = 90;
  currentAngle[3] = 30;
  base.attach(2);
  base.write(60);
  giunto.attach(4);
  giunto.write(30);
  polso.attach(3);
  polso.write(45);
  mano.attach(5);
  mano.write(30);
  angle[0] = 60;
  angle[1] = 30;
  angle[2] = 90;
  angle[3] = 30;
}

void loop(){
  switch(stato){
    case 0:
      letturaAngolo();
      movimento(angle[0], angle[1], angle[2], angle[3]); 
    break;
    case 1:
      letturaAngolo();
      movimento(angle[0], angle[1], angle[2], angle[3]);
      if(digitalRead(Pulsante1) == HIGH){
        values[INDEX][0] = angle[0];
        values[INDEX][1] = angle[1];
        values[INDEX][2] = angle[2];
        values[INDEX][3] = angle[3];
        Serial.print("pos base:");
        Serial.print(values[INDEX][0]);
        Serial.print("; pos gomito:");
        Serial.print(values[INDEX][1]);
        Serial.print("pos polso:");
        Serial.print(values[INDEX][2]);
        Serial.print("; pos mano:");
        Serial.print(values[INDEX][3]);
        Serial.println(";");
        INDEX++;
        delay(500);
      }
    break;
    case 2:
      Serial.println("Inizio movimenti programmati");
      for(int i = 0; i < 10; i++){
        movimento(values[i][0], values[i][1], values[i][2], values[i][3]);
        delay(500);
      }
      stato = 0;
    break;
  }

  if(digitalRead(Pulsante1) == HIGH && INDEX == 11){
    stato = 1;
    possibilities = false;
    INDEX = 0;
    Serial.println("lettura iniziata");
    delay(1000);
  }
  if(digitalRead(Pulsante2) == HIGH && possibilities == true){
    stato = 2;
  }
  if(INDEX == 10){
    if(millis() > intervalluzzo + tempo){
      Serial.println("lettura finita, premere pulsante 2");
      tempo = millis();
    }
    possibilities = true;
    stato = 0;
    INDEX = 11;
  }
}

void letturaAngolo(){
  if(digitalRead(SUbase) == HIGH && prevT[0] + intervallo < millis() && angle[0] >= 0 && angle[0] < 180){
    angle[0]++;
    prevT[0] = millis();
  }
  if(digitalRead(GIUbase) == HIGH && prevT[0] + intervallo < millis()&& angle[0] <= 180 && angle[0] > 1){
    angle[0]--;
    prevT[0] = millis();
  }  
  if(digitalRead(SUgiunto) == HIGH && prevT[1] + intervallo < millis() && angle[1] >= 0 && angle[1] < 180){
    angle[1]++;
    prevT[1] = millis();
  }
  if(digitalRead(GIUgiunto) == HIGH && prevT[1] + intervallo < millis()&& angle[1] <= 180 && angle[1] > 1){
    angle[1]--;
    prevT[1] = millis();
  }
  if(digitalRead(SUpolso) == HIGH && prevT[2] + intervallo < millis() && angle[2] >= 0 && angle[2] < 180){
    angle[2]++;
    prevT[2] = millis();
  }
  if(digitalRead(GIUpolso) == HIGH && prevT[2] + intervallo < millis()&& angle[2] <= 180 && angle[2] > 1){
    angle[2]--;
    prevT[2] = millis();
  }
  if(digitalRead(APRImano) == HIGH && prevT[3] + intervallo < millis() && angle[3] >= 0 && angle[3] < 180){
    angle[3]++;
    prevT[3] = millis();
  }
  if(digitalRead(CHIUDImano) == HIGH && prevT[3] + intervallo < millis()&& angle[3] <= 180 && angle[3] > 1){
    angle[3]--;
    prevT[3] = millis();
  }
}

void movimento(int x, int y, int z, int f){
  for(int a = 0; a < 180; a++){
    if(currentAngle[0] < x){
      currentAngle[0]++;
    }else if(currentAngle[0] > x){
      currentAngle[0]--;
    }
    if(currentAngle[1] < y){
      currentAngle[1]++;
    }else if(currentAngle[1] > y){
      currentAngle[1]--;
    }
    if(currentAngle[2] < z){
      currentAngle[2]++;
    }else if(currentAngle[2] > z){
      currentAngle[2]--;
    }
    if(currentAngle[3] < f){
      currentAngle[3]++;
    }else if(currentAngle[3] > f){
      currentAngle[3]--;
    }
    if(currentAngle[0] == x && currentAngle[1] == y && currentAngle[2] == z && currentAngle[3] == f){
      a = 180;
    }
    base.write(currentAngle[0]);
    giunto.write(currentAngle[1]);
    polso.write(currentAngle[2]);
    mano.write(currentAngle[3]);
    delay(25);
  }
}

Ora, come consigliato da @Salvorhardin nel post #90, ho intenzione di munirmi di motori passo-passo. Per evitare di fare lo stesso errore che ho fatto con i servomotori mi lascio fare consigliare da voi dei motori. (Non voglio spendere troppo possibilmente, considerando che ho 4 articolazioni e che la base ORA ha 2 servomotori per sorreggere tutto il peso)

Quali mi consigliate?

Quale servomotore mi consigliate di utilizzare per il braccio robotico? (budget: 100€ max)

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.