ASSIGNMENT: Write, or modify, an application that interfaces with an input and/or output device.
PROCESSING
I decided to work with Processing this week, since the interface is graphical, (somewhat) more intuitive and the environment well supported with tutorials. As Neil said, we all start out programming by modifying the code of others, so I focused on modifying tutorial code, code that I found to build a matrix of LEDs and an impressive application that I found working with a NeoPixel ring. Both my button board and WiFi board are still not working and I ran out of time to debug them further, so as it was suggested in this FabAcademy tutorial, I am using my mouse as an input device.
PATTERNS
First, I modified the "patterns" example found here on the Processing website. I modified the size, background and fill colors and the shape from an ellipse to rectangle in the draw functions. This is the code for the modified "patterns" example:
void setup() {
size(500, 500);
background(225,100,5);
noStroke();
fill(255,255,200,100);
}
void draw() {
// Call the variableRect() method and send it the
// parameters for the current mouse position
// and the previous mouse position
variableRect(mouseX, mouseY, pmouseX, pmouseY);
}
// The simple method variableRect() was created specifically
// for this program. It calculates the speed of the mouse
// and draws a small ellipse if the mouse is moving slowly
// and draws a large ellipse if the mouse is moving quickly
void variableRect(int x, int y, int px, int py) {
float speed = abs(x-px) + abs(y-py);
stroke(speed);
rect(x, y, speed, speed);
}
Here is a screenshot of the modifed "patterns" example:
2D ARRAY
I talked to Shawn about my final project and he told me how useful Processing can be for simulating animation. He said that Processing could be used to import images and animated gifs, analyze them and output data as frames of an animated sequence to an Arduino. This all sounded worthwhile exploring, but beyond my current beginner skill level and limited time to finish this week's assignment. He suggested that I start by using Processing to create an 8x10 array which mirrors the NeoPixel layout of the roof panels. He gave me an example of using nested "for loops" and I found a 2d array tutorial on the Processing website. In this code, I modified the size of the screen and size of the cells. I also modified the spacing between rows and columns to match the grid I will be making. Here is the code:
// 2D Array of objects
Cell[][] grid;
// Number of columns and rows in the grid
int cols = 10;
int rows = 8;
void setup() {
size(745,520);
grid = new Cell[cols][rows];
for (int i = 0; i < cols; i++) {
for (int j = 0; j < rows; j++) {
// Initialize each object
grid[i][j] = new Cell(i*80+8,j*70+8,10,10,i+j);
}
}
}
void draw() {
background(0);
// The counter variables i and j are also the column and row numbers and
// are used as arguments to the constructor for each object in the grid.
for (int i = 0; i < cols; i++) {
for (int j = 0; j < rows; j++) {
// Oscillate and display each object
grid[i][j].oscillate();
grid[i][j].display();
}
}
}
// A Cell object
class Cell {
// A cell object knows about its location in the grid as well as its size with the variables x,y,w,h.
float x,y; // x,y location
float w,h; // width and height
float angle; // angle for oscillating brightness
// Cell Constructor
Cell(float tempX, float tempY, float tempW, float tempH, float tempAngle) {
x = tempX;
y = tempY;
w = tempW;
h = tempH;
angle = tempAngle;
}
// Oscillation means increase angle
void oscillate() {
angle += 0.02;
}
void display() {
stroke(255);
// Color calculated using sine wave
fill(127+127*sin(angle));
rect(x,y,w,h);
}
}
Here is a screenshot of the modifed "2d Array" tutorial:
NEOPIXEL SEQUENCER
Lastly, I found an interesting Processing example using a GUI to assign RGB values to individual NeoPixels in a variable sized ring. This allows one to create individual frames of assigned color values and to thread the frames together to make an animated sequence. There is also the option to select the transition speed between frames, or slices. The animated sequence data can then be exported to a text file and incorported into an Arduino sketch and then output to NeoPixel ring.
This way by far the most complicated program I attempted to modify, but potentially the most useful one for me to keep working on to apply to my final project. I changed the sequence length from 16 to 25 slices and the maximum number of NeoPixels from 60 to 80. I created several animations and examined the hex output for each LED's RGB value in the text file. I attempted to change the NeoPixel ring to the matrix I created in the 2dArray exercise, but without luck. Here is the code:
import controlP5.*;
ControlP5 cp5;
ArrayList leds;
PFont myFontType;
ColorPicker colorPicker;
int colorPickerTop = 10, colorPickerLeft = 10;
float MAX_BRIGHTNESS = 1.0;
float MAX_SATURATION = 1.0;
float MAX_HUE = TWO_PI;
float MAX_ALPHA = 1;
PGraphics mainWin;
int selected = -1;
int currentFrame = 0;
int SEQUENCE_LENGTH = 25;
int NUMBER_OF_LED = 80;
float slice;
void setup() {
size(920, 1000);
//setup color picker
colorMode(HSB, MAX_HUE, MAX_SATURATION, MAX_BRIGHTNESS, MAX_ALPHA);
//colorMode(HSB);
colorPicker = new ColorPicker(colorPickerLeft, colorPickerTop);
mainWin = createGraphics(300, 280);
myFontType = createFont("arial", 16);
textFont(myFontType);
slice = PI/NUMBER_OF_LED;
//setup neo-pixel ring gui
rectMode(CENTER);
leds = new ArrayList();
for (int i = 0; i 2 && NUMBER_OF_LED!=newled) {
float spacing = newled*(8-newled/15.0);
if(NUMBER_OF_LED < newled) {
for (int i = NUMBER_OF_LED; inewled; i--) {
leds.remove(i);
}
}
NUMBER_OF_LED = newled;
slice = PI/NUMBER_OF_LED;
cp5.get(ColorMatrix.class, "LED_sequence").setGrid(SEQUENCE_LENGTH, NUMBER_OF_LED);
}
}
Here is a screenshot of the modifed "NeoPixel Sequencer" application:
CODE
Here is the code I modified for the Patterns test.
Here is the code I modified for the 2d array test.
Here is the code I modified for the NeoPixel test.
RESOURCES
Processing tutorials: Processing website
Shawn's simple serial stub, which is a starting point for Processing to communicate with an Ardruino scketch.