Allez, en ce dimanche très pluvieux j'ai essayé d'écrire quelque lignes de code pour tester le concept.
Voici le programme Processing:
import java.awt.*; // java.awt.Robot, java.awt.Rectangle, java.awt.AWTException
import processing.serial.*;
Serial arduinoSerial; // le Port Série
PImage copieEcran;
static final int period = 1000;
long chrono = -period;
color dominante;
boolean faireUneCopieEcran()
{
try {
copieEcran = new PImage(new Robot().createScreenCapture(new Rectangle(0, 0, displayWidth, displayHeight)));
}
catch (AWTException e) {
}
return (copieEcran != null);
}
color calculeCouleurDominante()
{
if (copieEcran == null) return color(0, 0, 0, 255);
long sommeR = 0;
long sommeG = 0;
long sommeB = 0;
int w = copieEcran.pixelWidth;
int h = copieEcran.pixelHeight;
long nbPixels = w * h;
copieEcran.loadPixels();
for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
color couleur = copieEcran.pixels[y*w+x] ;
sommeR += red(couleur);
sommeG += green(couleur);
sommeB += blue(couleur);
}
}
return color(sommeR / nbPixels, sommeG / nbPixels, sommeB / nbPixels);
}
void setup()
{
size(100, 100);
dominante = color(0, 0, 0); // noir
// List all the available serial ports:
printArray(Serial.list());
// Mettre comme N° la bonne entrée xxx dans la liste des ports séries Serial.list()[xxx]
arduinoSerial = new Serial(this, Serial.list()[7], 115200); // pour moi c'était 7
arduinoSerial.clear(); // vide le buffer
}
void draw()
{
if ((millis() - chrono) >= period) {
chrono += period;
if (faireUneCopieEcran()) {
dominante = calculeCouleurDominante();
println("Dominante:", red(dominante), green(dominante), blue(dominante));
String RGBDescription = red(dominante) + "," + green(dominante) + "," + blue(dominante) + "\n";
arduinoSerial.write(RGBDescription); // on l'envoie vers l'arduino
}
if (copieEcran != null) {
// image(copieEcran, 0, 0, width, height); // affiche la capture d'écran
background(dominante);
}
}
}
void serialEvent(Serial aPort) {
// on lit ce que nous dit l'arduino
while (aPort.available() > 0) print((char) aPort.read());
}
approche de base: j'ouvre la communication Série sur un port sur lequel j'ai accroché mon Arduino. pour cela il faut regarder dans la console de Processing la liste des ports Séries qui s'affiche et prendre le N° correspondant à celui de votre Arduino (pour moi c'était 7) et le mettre dans la ligne de commande arduinoSerial = new Serial(this, Serial.list()[7], 115200); // pour moi c'était 7
Le code n'est pas super compliqué si vous avez fait un peu de Java / Processing. J'ouvre une petite fenêtre de 100x100 que je vais colorier avec la couleur dominante de mon écran. Pour aller chercher cette dominante, je fais une capture d'écran toutes les 1000 ms (=1s) (période définie avec
static final int period = 1000;
) et j'ai pris l'approche de base un peu bourrin qui consiste à faire la moyenne arithmétique des R, G et B de la copie d'écran.
Une fois la moyenne effectuée, je crée un petit message sous la forme
[color=red]rrr[/color],[color=green]ggg[/color],[color=blue]bbb[/color]\n
que j'envoie sur le port Série.
Côté arduino voici le programme qui écoute ce qu'on lui dit:
const byte tailleMessageMax = 50;
char message[tailleMessageMax + 1]; // +1 car on doit avoir un caractère de fin de chaîne en C, le '\0'
const char marqueurDeFin = '\n';
boolean ecouter()
{
static byte indexMessage = 0; // static pour se souvenir de cette variable entre 2 appels consécutifs. initialisée qu'une seule fois.
boolean messageEnCours = true;
while (Serial.available() && messageEnCours) {
int c = Serial.read();
switch (c) {
case marqueurDeFin:
message[indexMessage] = '\0'; // on termine la c-string
indexMessage = 0; // on se remet au début pour la prochaine fois
messageEnCours = false;
break;
default:
if (indexMessage <= tailleMessageMax - 1) message[indexMessage++] = (char) c; // on stocke le caractère et on passe à la case suivante
break;
}
}
return messageEnCours;
}
void setup() {
Serial.begin(115200);
while (Serial.read() != marqueurDeFin); // on ignore la premier message
}
void loop() {
if (! ecouter()) {
// on a reçu le marqueur de fin
uint8_t rouge = 0, vert = 0, bleu = 0;
char * ptr = message;
if (ptr) rouge = atoi(ptr);
ptr = strchr(ptr, ',') + 1; // http://www.cplusplus.com/reference/cstring/strchr/
if (ptr) {
vert = atoi(ptr);
ptr = strchr(ptr, ',') + 1;
if (ptr) bleu = atoi(ptr);
}
Serial.print(F("[R:")); Serial.print(rouge);
Serial.print(F(" G:")); Serial.print(vert);
Serial.print(F(" B:")); Serial.print(bleu);
Serial.println(F("]"));
// ici affecter la couleur du bandeau lumineux
}
// ici on peut faire autre chose
}
qui reprend le code de mon petit tuto sur la lettre du port Série.
Une fois reçu le [color=red]rrr[/color],[color=green]ggg[/color],[color=blue]bbb[/color]\n
, on extrait les 3 composantes et je refabrique un petit message que je renvoie sur le port Série de l'Arduino à destination du programme Processing.
à la fin du programme Processing il y a la fonction serialEvent()
qui écoute et imprime dans la console de Processing tout ce qu'on reçoit.
[color=purple]
[color=orange][nobbc][0][/nobbc] "/dev/cu.Bluetooth-Incoming-Port"
[1] "/dev/cu.MALS"
[2] "/dev/cu.SOC"
[3] "/dev/cu.usbmodem1101"
[4] "/dev/tty.Bluetooth-Incoming-Port"
[5] "/dev/tty.MALS"
[6] "/dev/tty.SOC"[/color]
[color=red][7] "/dev/tty.usbmodem1101"[/color] [color=blue]<=== MON ARDUINO[/color]
Dominante: 167.0 190.0 191.0 [color=blue]l'arduino reboots ici, ne voit pas celui là[/color]
Dominante: 167.0 190.0 191.0 [color=blue]on saute celui là dans le setup()[/color]
Dominante: 167.0 190.0 191.0 [color=blue]<=== émission[/color]
[R:167 G:190 B:191] [color=blue]<=== Réponse de l'Arduino. bien lu !![/color]
Dominante: 137.0 122.0 111.0 [color=blue]<=== émission[/color]
[R:137 G:122 B:111] [color=blue]<=== Réponse de l'Arduino. bien lu !![/color]
...
[/color]
BIEN SUR NE PAS OUVRIR LA CONSOLE DE L'IDE ARDUINO, IL FAUT LAISSER LE PROGRAMME PROCESSING PRENDRE LA MAIN
--> voilà, avec ça vous recevez une fois par seconde la couleur moyenne (j'ai essayé s'il y a vraiment une dominante franche ça fonctionne) et vous avez un R/G/B côté arduino qui va vous permettre de piloter votre ruban.
Amusez vous bien