1

I wanted to install a 5 LED strip underneath my PC's front panel. I want to send color over PC so it can change when i open different apps, with temperature or etc!

So all I think the best way to do this is to just use Arduino to set the LED Values!

But I have had some troubles creating a good communication protocol for this, I've been just simply sending 45 digits (15 3 digit numbers) to my Arduino with serial. here's code: Arduino :

#include "Adafruit_NeoPixel.h"
#include "WS2812_Definitions.h"

#define PIN 4
#define LED_COUNT 5

struct pixel {
  int R = 0;
  int B = 0;
  int G = 0;
};

Adafruit_NeoPixel leds = Adafruit_NeoPixel(LED_COUNT, PIN, NEO_GRB + NEO_KHZ800);

char count = 1;
int pixelNumber = 0;
struct pixel tempPixel;
//struct pixel Pixels[LED_COUNT];

void setup()
{
  Serial.begin(9600);
  Serial.println("Init");
  leds.begin();  // Call this to start up the LED strip.
  clearLEDs();   // This function, defined below, turns all LEDs off...
  leds.show();   // ...but the LEDs don't actually update until you call this.
}

void loop() {
  if(Serial.available() > 0) {
    if(count == 1) {
      tempPixel.R = PC_Receive();
    } else if (count == 2) {
      tempPixel.G = PC_Receive();
    } else if (count == 3) {
      tempPixel.B = PC_Receive();
      count = 0;

      setPixelColor(pixelNumber, tempPixel);
      Serial.println(pixelNumber);
      leds.show();
//      Pixels[pixelNumber] = tempPixel;
      if(++pixelNumber >= LED_COUNT) {
        pixelNumber = 0;
      }
    }
    count++;
  }

//  if(pixelNumber == 0) {
//    for(int i = 0; i < LED_COUNT; i++ ) {
//       setPixelColor(i, Pixels[i]); 
//    }
//    
//    leds.show();
//  }
}

void setPixelColor(int a, struct pixel P)
{
  leds.setPixelColor(a, P.R, P.G, P.B);
}

char PC_Receive() {
  int result = 0;

  while(Serial.available() == 0);
  result += ((int)Serial.read() - '0') * 100;

  while(Serial.available() == 0);
  result += ((int)Serial.read() - '0') * 10;

  while(Serial.available() == 0);
  result += ((int)Serial.read() - '0');

  Serial.println(result);
  return result;
}







void setColourRgb(unsigned int red, unsigned int green, unsigned int blue) {
  for(int i = 0; i < LED_COUNT; i++) {
    leds.setPixelColor(i, red, green, blue);
  }
  leds.show();
 }

And here's PC's dirty code in python:

import serial
import time
import random

class Pixel:

    def __init__(self, R, G, B):
        self.R = R
        self.G = G
        self.B = B

def clearAll():
    for i in range(0,5):
        ser.write("000000000")

def sendPixel(pixels):
    for i in range(0,5):
        ser.write(str(pixels[i].R).zfill(3))
        ser.write(str(pixels[i].B).zfill(3))
        ser.write(str(pixels[i].G).zfill(3))


ser = serial.Serial('/dev/ttyACM2', 9600)

little = [0,0,0,0,0]

for i in range(0,5): 
    little[i] = Pixel(0,255,50)
sendPixel(little)

time.sleep(0.5)
clearAll()

the problem is it isn't stable, i think i should just use an \n at end or send back OK or something to confirm it, but that would make it slow if i did it for each value! (and checking only once after all 5 leds are send would mean sending more values until i receive the ok and clearing and sending them again!)

Can you recommend me a better way?

Thanks!

EDIT: Just wanted to say! it's almost done! It does change color when i open chrome, and i think at 115200 baud rate it's fast enough to not notice a delay (although at 9600 i felt like it's slower then my (xxx/xxx/xxx....) protocol but it's better and works at 115200

i will add some basic functions to my python side and add a rainbow effect I will also add GPU temperature and etc... it's not going to be really hard on linux but windows, im not sure :D

user3033693
  • 115
  • 3
  • Please edit your question and include the Arduino's setup() function as well. The code doesn't make sense when includes, variable declarations, and initialization code isn't shown. That is not to say it will make sense when they are shown :), merely that without them it doesn't. – James Waldby - jwpat7 Jan 04 '16 at 19:34
  • I don't think you need to worry about speed or data size from what you've described. Prioritise for ease of coding and reliability. Forget all the binary stuff. Send whole bytes. Start with a known sequence, and end with a known sequence of bytes and take advantage of the arduino's readBytesUntil function to find those start and end sequences. This avoids problems with the arduino getting out of sync and picking up the data stream partway through, causing lighting mayhem – Greg Woods Jan 05 '16 at 11:44

2 Answers2

1

I would recommend a similar solution as DaveX with a small modofication.

If you bitmask your LEDS, and leave room for a possible additional 3, you can mask any combination of them in the space of 00-FF. then you could send to the arduino a single string of 0xFFFFFFFF FF(LED bitmask),FF(Red value), FF(Green Value), FF(Blue Value).

so LED 1 {00000001 =01} all red {FF0000} would be 0x01FF0000

LED 2 and 4 {00001010 =0A} all green {00FF00} would be 0x0A00FF00

LED 5 and 1 {00010001 =11} all blue {0000FF} would be 0x110000FF

ALL LEDS off would be 0xFF000000

All LEDS onn full white would be 0xFFFFFFFF

FatherStorm
  • 144
  • 2
  • my led's are barely going to be the same color, so is it still worth using this? I think sending them in a chunk (but still binarry to reduce the size) will be easier! but im not sure how to convert a hex string to integer in arduino side, also im not sure how i can turn a int into hex string in python but i guess that one will be easy! – user3033693 Jan 05 '16 at 09:36
  • AFAIK C++ treats all numeric values as binary to start with, so if you say that rgbRED=127 it's the same as saying rgbRED = 0x7F – FatherStorm Jan 05 '16 at 14:33
  • Here is a file with some likely colors as well as an interactive RGB slider and LED picker so you can generate the values you would need.. https://marvinfrancois.com/19228.php – FatherStorm Jan 05 '16 at 15:49
  • Thanks a lot! as I'm inexperienced with these kind of stuff it will take em a lot of time, and googling :) but i will try to do it :) thanks a lot! – user3033693 Jan 05 '16 at 16:04
  • btw, just wanted to say, it's underneath my pc pointed to gound, it's a 5 strip led which EACH led has 3 colors, so it can be 5 different colors – user3033693 Jan 05 '16 at 16:06
  • Not sure if you're using the neopixel library, but if it's a strip of addressable LEDs, that may make your coding easier. I updated the page I pointed you at with some example arduino code that will update with the values you set, both which led and what color.. you'll still need to write your own logic for when to actually update and how you are getting your value in. I will work on it for a bit more to see if I can get it to decode the values the way I suggested, but I don't have an arduino with me so can't test the code.. – FatherStorm Jan 05 '16 at 16:24
0

I'd recommend adding digits to a digit register, setting the an R,B,G register with R,B,G and setting values of led a-e to the RBG registers when you get an a-e, ignoring whitespace, and clearing the register otherwise. So:

 ser.write("xRBGabcde\n")  # clear all the LEDs
 ser.write("x127RBb")       # make led b half-purple, relying on prior state 
 ser.write("x255Gc")        # make led c greenish-white    
Dave X
  • 2,332
  • 14
  • 28