Je suis actuellement sur le projet # 14 du livre de projet Arduino.
J'essaie de contrôler une esquisse de traitement sur mon ordinateur portable à l'aide de mon Arduino. Ceci est accompli en utilisant un potentiomètre pour contrôler l'arrière-plan d'une image.
Code Arduino:
void setup(){
Serial.begin(9600);
}
void loop(){
Serial.write(analogRead(A0)/4);
}
En traitement:
//imports serial library
import processing.serial.*;
//setups the serial object
Serial myPort;
//creates an object for the image
PImage logo;
//variable to store background color
int bgcolor = 0;
void setup(){
colorMode(HSB,255);
logo = loadImage("http://arduino.cc/logo.png");
size(logo.width,logo.height);
println("Available serial ports");
println(Serial.list());
myPort = new Serial(this,Serial.list()[0],9600);
}
//equivalent of arduino's loop function
void draw(){
if(myPort.available() > 0)
{
bgcolor = myPort.read();
println(bgcolor);
}
background(bgcolor,255,255);
image(logo,0,0);
}
Maintenant, alors que le code fonctionne et que la couleur d'arrière-plan change lorsque je tourne le potentiomètre, il y a un énorme décalage entre tourner le potentiomètre et voir la couleur changer d'arrière-plan, et les valeurs de l'Arduino / potentiomètre changent sur le moniteur série du traitement.
Ce que j'ai essayé:
- Modification de la vitesse de communication série
J'ai remarqué que lorsque je diminuais la vitesse de communication série, par exemple autour de 100, le délai entre tourner le potentiomètre et le voir changer sur mon ordinateur portable diminuait à environ 1 seconde. Cependant, lorsque je diminue encore plus la vitesse de communication série, par exemple une valeur de 1, le retard augmente à nouveau.
D'un autre côté, à la vitesse standard de 9600, le retard est énorme, environ 5 secondes ++ avant que les changements de potentiomètre n'apparaissent sur l'ordinateur portable / traitement.
Pourquoi la diminution de la vitesse de communication (jusqu'à un certain point) diminue-t-elle le décalage temporel et l'augmentation augmente-t-elle le décalage temporel? De plus, est-il possible de le faire presque instantanément?
la source
loop()
. Il est fort possible que votre programme de traitement ne fonctionne pas assez rapidement pour le suivre. Essayez de mettre un retard dans leloop()
code Arduino pour le ralentir; par exempledelay(50)
.Réponses:
Vous produisez une lecture à chaque fois autour de l'Arduino
loop()
, il semble donc probable que votre programme de traitement ne fonctionne pas assez rapidement pour le suivre. Essayez de retarder leloop()
dans votre code Arduino pour le ralentir, par exemple:Autant que je sache, le traitement vise à fonctionner à un débit d'images constant, que vous pouvez modifier à l'aide de la
frameRate()
fonction. Par défaut, c'est 60 images par seconde, bien que cela puisse fonctionner plus lentement sur les anciens systèmes (ou lorsque vous exécutez un programme intensif). Vous pouvez vérifier sa vitesse d'exécution en lisant laframeRate
variable.L'introduction d'un retard de 50 millisecondes dans la boucle Arduino signifie qu'il sera mis à jour un peu moins de 20 fois par seconde. Cela signifie qu'il devrait être assez rapide pour les besoins de l'interface utilisateur, mais devrait également être bien dans les capacités de votre programme de traitement.
En ce qui concerne le débit en bauds (vitesse de communication), l'ajustement par des quantités arbitraires risque d'avoir des résultats imprévisibles. C'est parce que le matériel ne prend en charge que des vitesses spécifiques, et essayer d'utiliser autre chose peut entraîner une altération des données à l'autre extrémité. La
Serial.begin()
documentation contient des informations supplémentaires sur les débits en bauds pris en charge.la source
Comme déjà souligné, votre Arduino en dit trop trop vite. L'ajout
delay()
le ralentira, mais il continuera de crier sur Traitement. Idéalement, vous voulez que Processing demande la valeur quand cela vous convient, puis reçoive une réponse de votre Arduino.Entrez
SerialEvent()
.Contrairement à
loop()
votre Arduino etdraw()
en cours de traitement, tout ce qui se trouve à l'intérieurserialEvent()
ne s'excuse que lorsqu'il y a quelque chose de nouveau dans le tampon série. Ainsi, au lieu que Processing pose des questions le plus rapidement possible et que votre Arduino crie encore plus vite, ils peuvent avoir une conversation agréable et polie (asynchrone).Processing et Arduino ont tous deux un serialEvent. C'est serialEvent () sur l'Arduino et c'est serialEvent () dans Processing. En utilisant serialEvent des deux côtés, voici ce qui se passerait:
Le traitement envoie un caractère à la connexion série. Cela peut être n'importe quel caractère, mais si nous en prédéterminons un, nous pouvons filtrer toutes les demandes indésirables causées par exemple par un signal bruyant. Pour cet exemple, envoyons
V
chaque fois que nous voulons une nouvelle lecture de votre potmètre. Après l'envoi du personnage, nous continuons notre travail comme d'habitude. Ne pas attendre une réponse ici!Du côté de l'Arduino, rien ne se passe jusqu'à ce qu'il reçoive des données dans le tampon série. Il vérifie si le personnage entrant est un
V
, et nous avons de la chance. L'Arduino lit la valeur du potmètre une fois, envoie cette valeur en série une fois et revient à se détendre, en relaxant au maximum. Protip: termine la valeur par un caractère (*
dans notre cas). Cela vous aidera dans la prochaine étape.Le traitement fait son affaire de pixels d'interface habituels quand tout à coup il y a
une perturbation dans la force denouvelles données dans le tampon série. Il passe àserialEvent()
, et commence à lire les données série, jusqu'à ce que notre terminaison*
soit rencontrée. Sachant que c'était le dernier caractère à lire, nous pouvons maintenant stocker la valeur entrante dans une variable qui stocke la lecture de l'Arduino.C'est ça. Le traitement connaît désormais la nouvelle valeur du capteur et poursuit tout ce que nous lui demandons de faire. Pendant ce temps, votre Arduino profite de la météo ou envisage son existence jusqu'à ce qu'il y ait des données série entrantes.
la source
Votre boucle d'interrogation s'exécute à pleine vitesse de votre processeur et écrit sur le port série à chaque tour.
De cette façon, vous écrivez beaucoup plus souvent sur le port série qu'il ne peut en gérer.
Le port écrit les données aussi rapidement que vous les avez configurées et met en mémoire tampon les données provenant de votre programme trop rapidement , pour les écrire dès que possible. Si le tampon est plein, il laisse simplement tomber de nouvelles données.
Ce qui est important ici, c'est qu'il gardera l'ordre des valeurs: Il s'agit d'un tampon FIFO , fonctionnant dans l'ordre First In / First Out.
Ce qui se passe est la suivante:
la boucle remplit le tampon de port et le maintient à 100% plein.
Si vous tournez le potentiomètre, la valeur modifiée est écrite à la fin du tampon , le port fonctionne aussi vite que possible pour écrire tous les éléments du tampon, qui ont toujours l'ancienne valeur.
Et enfin la valeur qui vous intéresse. La valeur la plus récente que nous voulions voir immédiatement était à la fin du FIFO, et le premier entré / premier sorti signifie également le dernier entré / dernier sorti. Le contraire de ce que nous voulons.
La fréquence maximale de lecture de vos données est la fréquence à laquelle vous pouvez les écrire, vous devez donc utiliser au moins un délai suffisamment long pour écrire les octets à la vitesse actuelle du port.
Comme autre mesure indépendante pour éviter ce type de retard en général,
vous pouvez également régler la mémoire tampon d'écriture du port au minimum.
Cela entraînerait la suppression des données beaucoup plus tôt, au lieu de tamponner beaucoup en premier.
Bien sûr, dans de nombreuses applications, ce n'est pas ce dont vous avez besoin; Avec de la malchance, cela pourrait de toute façon fonctionner au début et devenir instable dans certaines situations lorsque le timing change en fonction de choses comme la charge du processeur, et il n'y a que quelques échantillons de données aléatoires qui sont supprimés. Un grand tampon se comporte généralement beaucoup plus déterministe, utilisez donc un grand tampon par défaut .
la source
Au lieu d'envoyer constamment des données série, n'envoyez des données que lorsque la valeur du potentiomètre a changé au-dessus d'un certain seuil.
la source
loop()
ne remplit pas le tampon de sortie avec des échantillons égaux, c'est bien. Mais il fonctionne toujours à pleine vitesse du processeur, qui peut être 100 fois plus rapide que nécessaire. Cela signifie qu'il peut toujours remplir le tampon à la limite rapidement si l'entrée change fréquemment, par exemple du bruit authreshold
- dessus , ou un changement continu en haute résolution (ce qui n'est pas le cas dans l'exemple d'application ici)Deux solutions simples qui sont garanties de fonctionner pour tous ceux qui sont toujours à la recherche: -
Augmentez le délai à 50 à 100 millisecondes.
Ajoutez ceci après le
Serial.begin(9600)
insetup()
;La deuxième étape est la plus importante. Cela n'a fonctionné pour moi qu'après avoir ajouté le code ci-dessus. Ce n'est pas mentionné très souvent dans de nombreux autres forums que j'ai consultés lorsque j'ai eu exactement le même problème.
la source