Lumière d'ambiance de bureau

Salut tout le monde,
J'ai réalisé un système d'éclairage avec un bandeau LED RGB pour mon bureau tout fonctionne nickel.

J'aimerais y rajouter l'option de pouvoir mettre les LEDs du bandeau à la même couleur que celle qui domine sur mon écran. Je sais pas si c'st très clair mais en gros j'ai besoin de récupérer la valeur des pixels de mon écran puis d'en faire une sorte de moyenne et d'envoyer ça via une liaison série.
Et je ne sais pas du tout comment m'y prendre surtout pour récupérer les couleurs.

merci d'avance

Alrick_Gr:
Salut tout le monde,
J'ai réalisé un système d'éclairage avec un bandeau LED RGB pour mon bureau tout fonctionne nickel.

J'aimerais y rajouter l'option de pouvoir mettre les LEDs du bandeau à la même couleur que celle qui domine sur mon écran. Je sais pas si c'st très clair mais en gros j'ai besoin de récupérer la valeur des pixels de mon écran puis d'en faire une sorte de moyenne et d'envoyer ça via une liaison série.
Et je ne sais pas du tout comment m'y prendre surtout pour récupérer les couleurs.

merci d'avance

Bonjour
en gros tu veux faire une pseudo approche ambilight
avec comme base l'affichage de ton ecran de PC ?

Ouais c'est exactement ça

Est-ce que tu veux que tout ton bandeau led soit de la même couleur ou pleins de parties différentes genre ambilight ?

Je pensais à des capteurs de couleurs genre ça :

Regarde bien la description du produit car il y a un exemple de code dans l'onglet "fiche technique".
Tu dois pouvoir trouver ça beaucoup moins cher sur amazon ou autres mais bon...

Nan je veux juste une seule couleur à la fois mais le truc c’est que je veux pouvoir utiliser mon écran en même temps donc faut un moyen de chopper les valeurs des couleurs logiciellement et pas avec un capteur

Alrick_Gr:
Nan je veux juste une seule couleur à la fois mais le truc c’est que je veux pouvoir utiliser mon écran en même temps donc faut un moyen de chopper les valeurs des couleurs logiciellement et pas avec un capteur

Bonsoir
regarde le projet ambibox
avec les interfaces hard supportées

Merci beaucoup c’est exactement ce qu’il me fallait je vais tester ça une fois chez moi

Il faut bien sûr un bout de code tournant sur le PC et capable de faire une capture d’écran, de l’analyser et d’envoyer une couleur sur un port de communication (USB/Série, bluetooth, IP/WiFi) vers l’arduino

Pour écrire ce bout de code vous pouvez utiliser Processing en utilisant les classes Java (java.awt.Robot, java.awt.Rectangle) et en appelant createScreenCapture().

Vous mettez ça ça dans une PImage et vous analysez les couleurs pour trouver « la dominante ». (Algo à construire, pas sûr qu’une simple moyenne des RGB vous donne un truc bien, au moins passer en HSB avec une pondération des H par S et B) bref —> faut décider comment faire)

Vous êtes géniaux merci pour tous vos conseils j’ai hâte de réaliser ce projet !

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

Wow je m'attendais pas à ce que quelqu'un m'aide autant c'est super cool !!!!
J'ai juste une question :
tu as branché chaque couleurs sur un GPIO ou tu as tout branché toutes es couleurs en meme temps sur une liaison i2c/spi/... ?

Non les couleurs arrivent depuis mon Mac (ou PC) sous forme d'un message texte sur la liaison Série (le port USB du PC) et ensuite dans le code elles sont extraites et vous avez 3 octets R,G,B --> il suffit de les utiliser pour piloter votre ruban au lieu de renvoyer un message à l'ordi.

Donc si j'ai bien compris l'arduino reçois les 3 couleurs en chaine de texte et en suite pour envoyer cette couleur aux LEDS j'utilise les PWM et des transitor MOSFET pour chauque couleur de LED ?

ça dépend de votre ruban de LED - qu'est-ce que vous avez ?

J'ai justement décrit ce que j'avais donc un Vcc, un GND pour chaque couleur avec un MOSFET dessus et tous les MOSFET sont branchés sur l'arduino

Je ne vois pas la description... quel type de ruban?

Mais oui si vous avez trois canaux, alors en PWM avec les valeurs R/G/B ça devrait le faire, comme quand vous réglez une couleur Manuellement aujourd’hui

Désolé j’ai pas la référence du ruban c’est un truc que j’ai récupéré.

En tout j’espère que ça va marcher !

salut
je déterre ce post car je viens de réaliser (enfin) l'éclairage (merci les vacances).
j'ai légèrement amélioré le programme coté moyenne des couleurs en mettant plus de contraste.
En gros au lieu d'ajouter les valeurs RGB de chaque pixels à 3 variable, j'ajoute la couleur la plus dominante de chaque pixel à la variable qui correspond.
Maintenant il me reste plus qu'à ajouter tout ça à mon gros programme.

Au passage si vous savez créer un .exe sur processing je suis preneur.

Pour la question sur processing Allez dans fichier / exporter
Vous pourrez choisir la plateforme pour un exécutable

Super merci beaucoup !!!

Juste deux derniers trucs :

dans le petit script en java comment faire pour ne pas ouvrir la petite fenêtre qui fait un carré avec la couleur dominante (je m'y connais pas trop en java même si j'ai vu que ca ressemble pas mal au C/C++)

et est il possible de lancer mon .exe depuis mon code arduino ?