sábado, 12 de abril de 2014

Arduino Web RGB



I created this simple python-Flask app to inteface with my Arduino.

I worked with an Arduino Nano mounted on a breadboard.
You can get an idea on how to wire yours reading this fritzing project.
http://fritzing.org/projects/simple-rgb-led-on-an-arduino-uno

The barebones of this project goes like this.

First we create route on our flask app to handle requests to the root of our webserver.

from flask import Flask
from flask import send_file
app = Flask(__name__)

@app.route('/')
def index():
    return send_file('templates/index.html')

if __name__ == '__main__':
    app.run(host='0.0.0.0')

The file we have as index.html has the following script to get where the user has clicked, get the pixel information, and send it thru ajax back to our python app via the /color route.

$(document).ready(function(){
    $( "#colorpicker" ).on( "click", function(e) {
        var pixelData = this.canvas
                            .getContext('2d')
                            .getImageData(e.offsetX, e.offsetY, 1, 1)
                            .data;
        var hex = rgbToHex( pixelData[0], pixelData[1], pixelData[2]);
        $.post('/color', { color: hex });
    });
});
function componentToHex(c) {
    var hex = c.toString(16);
    return hex.length == 1 ? "0" + hex : hex;
}

function rgbToHex(r, g, b) {
    return componentToHex(r) + componentToHex(g) + componentToHex(b);
}

Now, the route listening on /color receives the color, compacts the color information using only the two most significant bits of each color component, and sends it to the Arduino connected via serial.

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

def send_value( value ):
    char = str( chr( value ) )
    ser.write( char )

def rgb_to_6bit( rgb ):
    return int('00' + bin(int(rgb[0:1], 16))[2:].zfill(4)[0:2]
                + bin(int(rgb[2:3], 16))[2:].zfill(4)[0:2]
                + bin(int(rgb[4:5], 16))[2:].zfill(4)[0:2], 2)

@app.route('/color', methods=['GET', 'POST'])
def color():
    if request.method == 'POST':
        color = request.form['color']
        send_value( rgb_to_6bit( color ) )

Finally, the Arduino is listening all the time for any incoming information.
When it receives something, it converts the compacted RGB color into analog values, and controls the analog pins of the board with the proper value.

const int GREEN = 9;
const int BLUE = 10;
const int RED = 11;

const int rgb_val[] = { 0x00, 0x40, 0x80, 0xff };
const char mask = 3;
int rgb[3];

void six_bit_to_rgb( char color, int * rgb )
{
    char tmp;
    int i;
    tmp = color;
    for (i = 2; i >= 0; i--) {
        rgb[ i ] = 0xff - rgb_val[ tmp & mask ];
        tmp = tmp >> 2;
    }
}

void setup()
{
  // initialize the serial communication
  Serial.begin(9600);
  // initialize the pins as an output
  pinMode(RED, OUTPUT);
  pinMode(GREEN, OUTPUT);
  pinMode(BLUE, OUTPUT);
}

void loop() {
  byte rgb6bit;

  // check if data has been sent from the computer
  if (Serial.available()) {
    // read the most recent byte (which will be from 0 to 255):
    rgb6bit = Serial.read();
    six_bit_to_rgb( rgb6bit, rgb );
    // set the brightness of the LED:
    analogWrite(RED, rgb[0]);
    analogWrite(GREEN, rgb[1]);
    analogWrite(BLUE, rgb[2]);
  }
}

Full python and Arduino code at https://github.com/facutk/arduino_web_rgb

No hay comentarios:

Publicar un comentario