Domani pemeriggio faccio calcoli a mano
a me continua a non dare nulla in cambio solo nan.
Avete usato il mio sketch?
Certo
Infatti ne abbiamo misurato anche i tempi
E controllato gli angoli
Per un caso solo in effetti
guarda, per sicurezza ti metto qui il nostro programma, ottenuto copiando dal tuo...
#include <math.h>
float alpha;
float beta;
float gamma;
float x = 65;
float y = 32;
float R1 = 100;
float R2 = 50;
float R;
unsigned long int tempo;
void setup()
{
Serial.begin(9600);
}
void loop()
{
tempo = micros();
// qui aggiungere controllo per x=0, punto di singolarità
alpha = atan(y / x) * 57.296;
R = sqrt((x * x) + (y * y));
beta = acos(((R2 * R2) + (R1 * R1) - (R * R)) / (2 * R2 * R1)) * 57.296;
gamma = acos(((R * R) + (R1 * R1) - (R2 * R2)) / (2 * R1 * R)) * 57.296;
Serial.print(R);
Serial.print("; ");
Serial.print(alpha);
Serial.print("; ");
Serial.print(gamma);
Serial.print("; ");
Serial.print(beta);
Serial.print("; ");
Serial.print(micros() - tempo);
Serial.println();
delay(200);
}
e questo è la stampa
72.45; 26.21; 28.38; 43.52; 1668
72.45; 26.21; 28.38; 43.52; 1672
72.45; 26.21; 28.38; 43.52; 1676
72.45; 26.21; 28.38; 43.52; 1676
72.45; 26.21; 28.38; 43.52; 1676
72.45; 26.21; 28.38; 43.52; 1676
72.45; 26.21; 28.38; 43.52; 1668
72.45; 26.21; 28.38; 43.52; 1672
72.45; 26.21; 28.38; 43.52; 1672
72.45; 26.21; 28.38; 43.52; 1676
Basta calcolare alpha come: acos(x / R)
Vero è
Grazie mille per lo script!
Gli script sono quasi identici ma a me non funzionava, chissà perché? Nonostante ciò ora funziona tutto alla perfezione
Ora il prossimo passo è inserirlo nello script di azionamento del braccio robotico (per @Ducembarr, braccia quando si parla di esseri viventi e bracci per quelli non viventi come robot oppure automi etc. )
Ricapitoliamo:
Vogliamo muovere un punto x,y posto all'estremità di un braccio a 2 dof (degrees of freedom)
Il punto non potrà mai andare più lontano dall'origine di R1+R2, e non potrà mai essere più vicino all'origine di R1-R2.
Ci interessa determinare gli angoli a partire da x e y, e qui entra in gioco Carnot:
Almeno per il quadrante positivo i conti tornano (per x o y negativi non sono sicuro). Lascerei gli angoli sempre in radianti, meno calcoli e meno errori di arrotondamento, trasformandoli in gradi solo quando serve. Riprendo lo sketch precedente con qualche piccola modifica, così ho scoperto che anche in C++ c'è la funzione hypot. Eventualmente in ottica di ottimizzazione tempi si potrebbero calcolare i vari prodotti una sola volta.
#include <math.h>
float x = 65.0;
float y = 32.0;
float R1 = 100.0;
float R2 = 50.0;
const float DEG_CONVERSION = 180.0 / PI;
void setup() {
Serial.begin(9600);
float R = hypot(x, y);
float alpha = acos(x / R);
float beta = acos((R2*R2 + R1*R1 - R*R) / (2.0 * R2 * R1));
float gamma = acos((R*R + R1*R1 - R2*R2) / (2.0 * R * R1));
Serial.print("alpha=");
Serial.print(alpha * DEG_CONVERSION);
Serial.print(" R=");
Serial.print(R);
Serial.print(" beta=");
Serial.print(beta * DEG_CONVERSION);
Serial.print(" gamma=");
Serial.println(gamma * DEG_CONVERSION);
float new_x = R1 * cos(alpha + gamma) + R2 * cos(alpha + gamma + beta - PI);
float new_y = R1 * sin(alpha + gamma) + R2 * sin(alpha + gamma + beta - PI);
Serial.println("----------------------------------");
Serial.print("Verify: new_x=");
Serial.print(new_x);
Serial.print(" new_y=");
Serial.print(new_y);
}
void loop() {
}
Avevo provato
Incredibilmente sulla uno ci mette 400 microsecondi in più non capisco il motivo
Ciao a tutti di nuovo,
Ringrazio tutti per il loro aiuto e ne approfitto per chiarire qualche dubbio.
Le formule sono ora tutte corrette, ma il problema che riscontro adesso è in che modo fornisco ad Arduino le coordinate da raggiungere con il braccio robotico. Io le vorrei fornire da Seriale come x; y
. Ho cercato su internet e ho trovato delle spiegazioni su come fare, ma non ci riesco proprio a capirle. Ed è qui che torno a rivolgermi a voi Come posso fare?
per intanto bravo per essere arrivato fin qui
noi abbiamo affrontato questa cosa alcune volte, ma non siamo i soli
l'argomento "comando da seriale" ritorna spesso negli anni
una delle migliori descrizioni che "ricordiamo" della soluzione la ha data un certo "standardoil" che ne aveva scritto più volte
trovi argomenti suoi in stiky, ma comunque ti mettiamo il link
la sua spiegazione ci è parsa ai tempi buona, anche se un po' ampollosa
se hai domande prova a "chiamarlo" qui sul forum, non si fa sentire da un pezzo
altrimenti domanda c'è Fabio qui che ha la "vocazione dell'insegnate" e sbava all'idea di poter pontificare, io a dir la verità un po' meno, ma tra tutti e due
PS
nnon averne a male se ti rimandiamo ad altri e non ti "accompagnamo"
è intile scrivere e riscrivere sempre le stesse cose
ma se hai dubbi come già detto domanda
Grazie delle info. Intanto ho provato a sviluppare un codice tramite un video trovato su youtube. Il codice è il seguente:
void setup() {
Serial.begin(9600);
Serial.println("type: hello");
pinMode(13, OUTPUT);
}
String val1 = "";
String val2 = "";
byte val;
void loop() {
if(Serial.available()) {
char ch = Serial.read();
val = 0;
if((ch == '\n') || (ch == '\r')) {
while(1);
}else{
if(val = 0 && ch == ";"){
val = 1;
}
switch(val){
case 0:
val1 += ch;
break;
case 1:
val2 += ch;
break;
}
}
Serial.println(val1);
Serial.println(val2);
}
}
Il problema è che scrive tutto nella val1 e nulla nella val2. Ora vado a vedere i link che mi hai fornito
rottamalo quel codice
ed evita il suo autore in futuro, non è buona scuola
esempi:
uso di oggetti string
usa due variabili separate invece di un array di variabili
e quindi deve usare uno switch invece che indirizzare un indice
usa costanti letterali hard coded invece di define
pianta a fondo il ciclo con un while(1)....
Scusa ma stai andando un po'troppo sullo specifico, potresti spiegarti meglio per favore?
presumendo che tu stia usando una UNO o simile gli oggetti String sono da evitare
esse sono il male, il cattivo definitivo, il signore dei Sith
ogni caso d'uso delle variabili String su una UNO è erroneo e indice di cattiva programmazione, senza scusanti
per quanto riguarda il secondo punto
scrive
Val_1
Val_2
e quando arriverà a 10 o 20 cosa fa?
si usa un array di variabili
del tipo Val[2] o Val[20]
così invece di dover usare uno switch( e una serie di case(
basta usare val[indice]=
per le costanti letterali hard-coded
se scrivi in giro if(ch=='\r') in giro per il programma se e quando ti capiterà di dover cambiare il terminatore di riga ti tocca impazzire a rileggere tutto il programma cercando dove hai scritto '\r' sperando anche di trovarli tutto
se invece fai una
#define TERMINATORE '\r'
cambi una sola riga all'inizio
potrei aver frainteso io (probabilmente).
Il primo punto lo ho capito e ci lavoro su tra poco, mentre per il secondo non avrò mai dei numeri grandi 10-20 cifre perché il braccio robotico (ricordo che voglio immagazzinare le coordinate da raggiungere) è piccolo (R1 = R2 = 13cm, 1x = 1cm e 1y = 1cm). Quindi credo possa andare bene così, in caso contrario devo capire bene questa cosa. Mentre per il terzo punto credo di aver capito e adesso faccio subito. Grazie ancora
Ho rielaborato il codice ma ho peggiorato la situazione e basta.
Ora ho questo:
#define TERMINATOR1 '\r'
#define TERMINATOR2 '\n'
#define TERMINATOR3 ';'
char val1[20];
char val2[20];
byte val;
byte i;
void setup() {
Serial.begin(9600);
Serial.println("type: hello");
pinMode(13, OUTPUT);
}
void loop() {
if(Serial.available()) {
char ch = Serial.read();
val = 0;
if((ch == TERMINATOR1) || (ch == TERMINATOR2)) {
while(1);
}else{
if(val = 0 && ch == TERMINATOR3){
val = 1;
}
switch(val){
case 0:
val1[i] = ch;
i++;
break;
case 1:
val2[i] += ch;
i++;
break;
}
}
for(int i = 20; i > 1; i--){
Serial.print(val1[i]);
}
Serial.println();
for(int i = 20; i > 1; i--){
Serial.print(val2[i]);
}
}
}
E non me li scrive nella prima variabile e solo una parte. Credo di aver semplicemente scombussolato tutto e basta...
non è la dimensione della variabile il problema
ma il "numero" di variabili trasmesse
finoa che ragioni con manipolatori a due assi te ne bastano due
ma mi sembra che per veri manipolatori ce ne vogliano sei
hai voglia a scrivere sei volte case(..... break
molto meglio passare per un indice
vedi la ragione per usare un indice invece di uno switch case?
tu hai due pezzi di programma che "sembrano" uguali
in realtà ti è rimasto un "+=" dove dovresti mettere un "="
e non hai resettato l'indice i al passaggio del terminator3
Ho cambiato come dici te il += in = ma non è cambiato nulla
Questa cosa dell'indice non la ho capita. Adesso faccio due ricerche e poi vedo come modificare lo sketch.
Lo riallego per sicurezza:
#define TERMINATOR1 '\r'
#define TERMINATOR2 '\n'
#define TERMINATOR3 ';'
char val1[20];
char val2[20];
byte val;
byte i;
void setup() {
Serial.begin(9600);
Serial.println("type: hello");
pinMode(13, OUTPUT);
}
void loop() {
if(Serial.available()) {
char ch = Serial.read();
val = 0;
if((ch == TERMINATOR1) || (ch == TERMINATOR2)) {
while(1);
}else{
if(val = 0 && ch == TERMINATOR3){ //questo if serve a far scrivere i valori letti in una delle due stringhe. cambia stringa quando legge il punto e virgola
val = 1;
i=0;
}
switch(val){
case 0:
val1[i] = ch;
i++;
break;
case 1:
val2[i] = ch;
i++;
break;
}
}
for(int i = 20; i > 1; i--){
Serial.print(val1[i]);
}
Serial.println();
for(int i = 20; i > 1; i--){
Serial.print(val2[i]);
}
}
}