Objectif du projet : Faire varier un processus aléatoire de balles à l’aide d’une résistance variable (potentiomètre).
L’intensité de l’éclatement des balles se situe sur une abscisse «x». En tournant le potentiomètre de la gauche vers la droite, on obtient une destruction du chiffre «4». Cette destruction s’intensifie aussi en fonction de la rapidité du mouvement. Pour cela, il nous faut un montage arduino précis (voir ci-dessous), le sketch processing qui permet de faire varier une classe de balles, et la Librairie SerialCallResponse (sur arduino et processing).
Outils
- carte arduino + cable usb - potentiomètre - breadbord - 3 fils conducteurs
Montage
Sketch - ARDUINO
int firstSensor = 0; // Premier capteur analogique int secondSensor = 0; // Second capteur analogique int thirdSensor = 0; // Capteur numérique int inByte = 0; // Série des octets rentrant void setup() { Serial.begin(9600); // Commencer le port série à 9600 bps while (!Serial) { // // Attendre pour vous connecter au port série - Nécessaire pour Leonardo seulement } pinMode(2, INPUT); // "pinMode" définit la patte n°2 de la carte comme une sortie numérique / INPUT : establishContact(); // Envoie d'un octet pour établir un contact et avoir une réponse } void loop()// fonction execute une boucle sans fin, permetant au programme de s'exécuter et de répondre par un signal. Fonction qui test l'état du capteur a chaque passage et envoie un signal au pc si positif. { // instructions répétées une infinité de fois tant que la carte est sous tension if (Serial.available() > 0) { // if : conditient a executer si Serial.available est supérieur à 0 inByte = Serial.read(); // lecture de l'octet rentrant firstSensor = analogRead(A0)/4; // Lire la première entrée analogique, diviser par 4 pour faire la gamme 0-255: delay(10); // demande à la carte d'attendre 10ms Serial.write(firstSensor); } } void establishContact() { // parametrage pour établir le contact entre carte et ordinateur while (Serial.available() <= 0) { //instruction Serial.print('A'); // si on établi un contact : envoyer la lettre A delay(300); //demande à la carte de patienter 300ms= 1s en conservant l'état haut de la pate n°2 } }
Sketch Processing - Librairie Géomérative
import geomerative.*; //ouverture de la librairie import processing.serial.*; // import de la librairie "Serial my port" Serial myPort; // The serial port //int serialIn =0; // emplacement des signaux reçu int serialCount = 0; // compte du nombre d'octets reçu int xpos; // Position de la balle de départ (position en x) int inByte; boolean firstContact = false; // signale reçu du micro contrôleur - "false" état du boolean RFont font; //ouverture de la fonction Rfont PFont maTypo; ArrayList<Balle> ensembleBalles; //ArrayList c'est un tableau String texte = "4"; //fonction String : créer une chaîne de carcatères - ici chiffre 4 void setup() { //fonction appelé dès le lancement du programme : trouve les points vectoriel de la typo et les regroupe printArray(Serial.list()); // initialisation des ports série String portName = Serial.list()[0]; myPort = new Serial(this, portName, 9600); //9600 val size(800, 800); //taille de la fenêtre background(255); //couleur de fond smooth(); //anti pixellisation RG.init(this); //initialiser l'objet constructeur de la bibliothèque font = new RFont("FreeSans.ttf", 250, CENTER); // charger la typo par rapport a la librairie //typo pour le 4 + taille et placement maTypo = loadFont("HelveticaRoundedLT-Bold-48.vlw"); //changer la typo de "DESIGN" fill(0,0,0); //remplir avec une couleur noStroke(); //pas de contour autour des ensembleBalles RCommand.setSegmentLength(5);//ASSIGN A VALUE OF 10, SO EVERY 10 PIXELS RCommand.setSegmentator(RCommand.UNIFORMLENGTH); RGroup myGroup = font.toGroup(texte); //créer un objet de regroupement myGroup = myGroup.toPolygonGroup(); //il créer un assemblage avec la fonction myGroup RPoint[] myPoints = myGroup.getPoints(); //trouver tout les points d'encrage de la typo. myPoints : variable ensembleBalles = new ArrayList<Balle>(); //liste de balle sous forme de tableau for (int i = 0; i < myPoints.length; i++) { // boucle : trouver du 1er points jusqu'au nombre de points max trouver sur la forme //length : taille maxi //vue que j'ai mis la fonction length il cherche tout les points de la forme ensembleBalles.add(new Balle(myPoints[i].x + width /2, myPoints[i].y + height / 2)); //newball : add une balle - ensembleBalles : c'est le tableau qui coresspond a 195pts } } void draw() { //fonction appelé par un choix background(255); for (Balle b : ensembleBalles) { //pour toute les balle du tableau, meme action. b.miseAJour((float)xpos / width); b.affichage(); } pushStyle(); //ce qu'on met entre cette fonction ne s'applique pas au reste du sketch fill(115); //couleur typo textFont(maTypo, 50); //textSize(50); // taille typo text(" ", 150, 300); //typo intégré a côté du 4 popStyle(); //ce qu'on met entre cette fonction ne s'applique pas au reste du sketch }
PROCESSING - Serial Event
void serialEvent(Serial myPort) { // dis de lire ce que la carte arduino envoie/récupère les données de arduino int inByte = myPort.read(); //inByte = variable qui lis la valeur de ce qu'il y a sur le port usb if (firstContact == false) { if (inByte == 'A') { //dans la arduino envoyer un A si connecter/oupas si inByte est égale a A effacer le tampon du port série myPort.clear(); // effacer le tampon du port série firstContact = true; // détection des premiers contacts avec le microcontrolleur myPort.write('A'); } } else { // else = sinon xpos = inByte; println(xpos + "\t"); //xpos = valeur du potentiomètre myPort.write('A'); //signale détecté la lettre A } }
PROCESSING - Classe Balle
class Balle { PVector origine, destination, position; //créer trois objets PVector Balle(float x, float y) { //float:variable décimale - coordonées de la classe Balle en rapport avec myPoints (dessus) //PVector : permet de ne pas réecrire x et y et de combiné les deux coordonées origine = new PVector(x, y); //appel la classe Balle position = origine.get(); // destination = new PVector((int)random(0, width), (int)random(0, height)); //créer des destination au hasard pour la balle //random:fonction variable entière } void miseAJour(float parametre) { position = PVector.lerp(origine, destination, parametre); //lerp créer une transission entre le points d'origine et le point d'entrée } void affichage() { ellipse(position.x, position.y, 1, 2); //détermine le diamètre de l'ellipse de chaque balles } }