Leonardo - Mouse e movimento assoluto

Ciao a tutti ragazzi!
Vorrei chiedervi aiuto riguardo un problema che ho e che non riesco a risolvere con le mie nozioni su Arduino (in particolare, ho la scheda Leonardo) e sulle sue librerie.

So che Mouse.move muove il puntatore di tot pixel relativamente alla sua posizione attuale, mentre io
avrei bisogno, come da titolo, di usare le librerie del mouse per eseguire un movimento assoluto del puntatore in modo da assegnare delle coordinate all’origine dello schermo (al centro, magari) e muovere il puntatore sullo schermo, a seconda dei valori che gli passerò, relativamente a quell’origine.
Ovviamente, se dopo essersi mosso non gli viene passato altro, deve rimanere fermo in attesa di altri valori, esattamente come funziona un mouse reale.

Ho provato a usare un suggerimento scritto qua

ma non capisco bene cosa devo includere nell’esempio che viene portato.

Non devo scrivere
#include <HID.cpp>
ma
#include <Mouse.h>
immagino…però Mouse.h si riferisce da solo al file HID.cpp o devo fare altro?

Tra l’altro nel post si dice di sostituire il HID presente con questo nuovo ma dal momento che non ho il file HID e Mouse.h funziona lo stesso ho il dubbio che ci si riferisca a una vecchia versione di Arduino IDE e che ora HID non venga più usato. Potete darmi conferma e aiutarmi?

Grazie mille :wink:

Lasciando perdere quel che suggerisce quel post (che oggi sarebbe più semplice grazie al supporto Pluggable USB introdotto recentemente... forse), la butto lì: hai provato a fare una serie di movimenti verso l'alto e verso sinistra in numero sufficiente da risultare maggiori della risoluzione dello schermo in modo da essere certo che alla fine il puntatore si trova nell'angolo in alto a sinistra? Da lì poi è facile andare dove vuoi, anche con movimenti relativi, che diventano di fatto assoluti.

Se funziona, è più facile a farsi che a dirsi ;).

può essere un'idea quella di inizializzare il puntatore in alto a sinistra (anche se preferirei fosse al centro), però una volta portato là, inserendo dei valori, il puntatore si sposta (relativamente e anche assolutamente) dei pixel che desidero.

Al successivo ciclo però, il puntatore non sarebbe più in alto a sinistra e quindi, ricevendo di nuovo quei valori che gli passo, si sposterebbe ulteriormente senza che io abbia cambiato i valori, mentre vorrei che stesse fermo.....giusto?

Il centro dello schermo è abbastanza scomodo come punto di riferimento, ad esempio perché dipende dalla risoluzione, e da Arduino non puoi certo determinarla. A memoria non ho mai visto utilizzare un sistema del genere. Di solito lo (0,0) è in altro a sinistra o, a volte, in basso a destra.

Volendo usare il primo, puoi fare una cosa del genere:

void home() {
  Mouse.move ( -10000, -10000);
}

void moveAbs(int x, int y) {
  home();
  Mouse.move (x, y);
}

Dovrebbe funzionare sempre, magari non sarà bellissimo da vedere, ma dovrebbe essere talmente veloce...

oh ecco, ok. Questo va bene, ma non vorrei che facesse avanti e indietro.
Cioè, mi servirebbe un modo per cui lui memorizza che home è (0,0) ma senza portarci il mouse se non la prima volta.
Non è un fatto di estetica il movimento "inconsulto" tra posizione su home e sul punto desiderato, a me andrebbe anche bene, è che non è molto funzionale.

Potrebbe essere tipo:

int x = -10000;
int y = -10000;

void setup()
{
   //Porto il puntatore in alto a sinistra
   Mouse.move(x,y);
}

void loop()
{
  //variabili che gli passo dall'esterno
  int a;
  int b;

  Mouse.move(x+a,y+b);

  //aggiorno x e y in modo che x+a e y+b siano il mio nuovo riferimento
  int x=x+a;
  int y=y+b;
}

Però in questo caso sono punto e a capo perchè al seguente ciclo me lo sposterà di nuovo.
Avrei bisogno di una condizione per cui se le nuove a e b sono uguali alle precedenti (quindi il mouse non si è mosso) non esegue Mouse.move e anche il puntatore resta fermo

Perché non è molto funzionale? Prendi le due funzioni che ti ho scritto sopra, e ogni volta che vuoi muoverti invece di fare Mouse.move(x, y) fai moveAbs(x, y).

In alternativa puoi tenere traccia di dove sei e ad ogni nuovo movimento calcolare l'offset di cui spostarti a partire dalle coordinate assolute, ma è più laborioso e in prima approssimazione non vedo perché seguire questa strada.

Cioè, funziona, non dico di no ma non posso far vedere che il mouse fa su e giù in continuazione da Home alla posizione che gli do.
Non me la accettano visualmente questa soluzione.

Magari ora provo perché se è veloce come dici può anche andare, se non si nota il movimento.
In questo caso come le implemento le funzioni che hai scritto?
Le metto entrambe nel loop?

Altrimenti..... Com'è quella cosa del offset?

A parte che prima hai detto l'esatto contrario, secondo me è talmente veloce che non te ne accorgi neanche, prova almeno.

Funzioni nel loop()? :o Direi di no... Mettile prima di setup()...

Non me lo accettano visualmente nel senso che darebbe fastidio a livello visivo, non perché è brutto, ma proprio perché vedere il mouse muoversi in modo inconsulto su e giù potrebbe essere fastidioso.
Non so se mi sono spiegato adesso :wink:

Comunque provo, si si! Assolutamente

Ecco, qua arriva la parte dolente, nel senso che non so bene come devo inserire le funzioni.
Cioè, nel setup va ciò che viene eseguito una volta sola e in loop quello che viene eseguito continuamente, giusto?
Quindi se le funzioni le metto prima di setup (non sapevo di poter aggiungere funzioni all'esterno, credevo leggesse solo setup e loop) in loop vanno richiamate?

Non puoi definire funzioni all’interno di altre funzioni. setup() e loop() sono normali funzioni, puoi definirne quante ne vuoi esattamente allo stesso modo, come ho fatto io sopra.

Definire una funzione dice solo quel che la funzione fa, ma non viene mai chiamata automaticamente (tranne setup() e loop(), in questo aspetto sono “speciali”), per cui da qualche parte dovrai chiamarla tu. Visto che il tuo programma inizia per forza da setup() e loop(), devi richiamarla da lì, o da un’altra funzione che è chiamata a sua volta da lì. Insomma, chiamala quando vuoi muovere il mouse!

Più facile a farsi che a dirsi ;).

Ok perfetto! Grazie mille! Provo :wink:

Risultato: ho provato a implementare le funzioni scritte da te e a metterle nel setup con un ciclo

void setup() {
  int i=1;
  while(i<100){
    moveAbs(10*i,10*i);
    i=i+2;
  }
}

però non si muove, mentre con un ciclo for con le medesime condizioni si muove ma continua imperterrito, dopo essere tornato alla home, a andare avanti della stessa quantità, invece che aumentare con il fattore i.

Cosa sbaglio? :-/

Il problema è esattamente il contrario: si muove talmente veloce che sembra fermo! Devi mettere un delay() da qualche parte.

ah vero! Bene!
Allora adesso stavo facendo alcune prove e ho visto che con i valori che mi hai dato non riesco a mandare il mouse un alto a sinistra, cioè ci va ma non arriva all'angolo e quindi la sua Home cambia sempre.
Ho provato a inserire dei valori più grandi (in valore assoluto, quindi col - più piccoli) ma poi credo di uscire dal range degli int e non si muove più il puntatore.
Come potrei fare?

Sto comunque valutando l'idea dell'offset per memorizzare la posizione e muoverlo solo se effettivamente i valori cambiano

Puoi provare a mettere fino a -32768, ma è più facile mettere -10000 e infilare il tutto in un for che lo ripete un po' di volte. O chiamare direttamente la funzione più volte.

Dunque però da questo capiamo che l'unità di misura non sono i pixel... >:(

ciao! Perdonami per il ritardo della risposta ma sono sotto studio matto e disperato (ultimo esame).
Ho trovato una buona soluzione.

Ti rigiro il link di gitHub della libreria.

L'ho provato e mi sembra funzionare molto bene, ma non capisco come lavora....in termini tecnici.
A parte il fatto che lui dice che x=0 e y=0 è il centro dello schermo mentre a me parte comunque dall'angolo in alto a sinistra usando la funzione AbsoluteMouse.moveTo(0,0), non capisco come funziona il codice tra valori esadecimali e le altre funzioni.

potresti aiutarmi a capire? :slight_smile:

Quella "libreria" è in realtà una modifica del core di Arduino, cosa che a me piace poco, come già detto sopra.

Non ho ancora avuto tempo di testare la mia soluzione, ma sono sempre convinto che smanettandoci un po' si possa ottenere quel che vuoi. Hai provato a fare quanto detto prima?

Ciao! Passato l'esame eccomi di nuovo :slight_smile:
Allora, ho provato la soluzione che hai proposto (quella di usare Mouse.move(-10000,-10000) in un ciclo e poi muovere il mouse inserendo i valori in Mouse.move(x,y)) però purtroppo non va. Nel senso che, da quanto ho capito, Mouse.move() riceve in ingresso dei valori "signed char" e quindi va da -127 a 127. Andando oltre, se ho ben capito, ricomincerà il giro, quindi impostando 128 sarà come se leggesse 0, 129 sarà -1 (quindi mi cambia verso), ecc.
Per portarlo all'angolo in alto a sinistra non ho problemi perchè cicla e torna su, ma il fatto che mi cambia verso di movimento, superando i valori detti, mi crea problemi.
Inoltre, ogni volta dovrei dirgli di muoversi al massimo di 127 o -127, però poi dovrei fargli memorizzare la posizione prima di farlo ritornare alla home, in modo da farlo ripartire da là (visto che ho sempre questi limiti di 127 o -127)......non so se ho spiegato bene problema e ipotesi di soluzione molto abbozzata :confused:

Hai ragione, il fatto che gli argomenti siano signed char rende le cose un po’ più scomode. Ho finalmente fatto qualche test e messo a punto il seguente sketch, che sembra funzionare come deve, anche se l’effetto di mandare il mouse in alto a sinistra non è del tutto invisibile come speravo. Mi sa che è meglio seguire la strada del tenere traccia della posizione e spostarsi solo del dovuto.

Ancora meglio sarebbe sfruttare il supporto Pluggable HID e aggiungere la possibilità di posizionamento assoluto senza dover modificare le librerie. Se mai mi servirà, guarderò se è possiible, per il momento mi accontanto di questo ;).

#include "Mouse.h"

#define DELTA 127

void home() {
  /* Qui in teoria si potrebbe usare -128, ma non sembra funzionare, mah!
   * All'atto pratico cambia poco...
   */
  for (byte i = 0; i < 20; i++)
    Mouse.move (-DELTA, -DELTA);
}

void moveAbs(int x, int y) {
  home();
  do {
    signed char dx = min (x, DELTA);
    x -= dx;

    signed char dy = min (y, DELTA);
    y -= dy;
    
    Mouse.move (dx, dy);
  } while (x > 0 || y > 0);
}

void setup() {
  Mouse.begin();
}

void loop() {
  for (int x = 0; x < 1000; x += 100) {
    moveAbs (x, x);
    delay (1000);
  }
}

ah ora lo provo! Grazie!
Perdonami ma col C non me la cavo granchè, sono più pratico col Java.
In pratica, cosa gli dici?

  • Ogni volta che esegue moveAbs prima fa home() e sposta il mouse di quel DELTA che hai definito
    (#define DELTA 127 vuol dire che è una variabile statica?)
    (perchè il for usa la variabile di tipo byte?)

  • dopo home(), lui definisce dx e dy come il minimo tra x e DELTA o y e DELTA
    (perchè?)

  • infine sposta il mouse di dx e dy

Esatto?