diff --git a/Raspberry_Pi_Video_Synth/BlinkaRaspberryPiVideoSynth.py b/Raspberry_Pi_Video_Synth/BlinkaRaspberryPiVideoSynth.py new file mode 100644 index 000000000..fe1916eb5 --- /dev/null +++ b/Raspberry_Pi_Video_Synth/BlinkaRaspberryPiVideoSynth.py @@ -0,0 +1,141 @@ +# SPDX-FileCopyrightText: 2022 Liz Clark for Adafruit Industries +# +# SPDX-License-Identifier: MIT + +import socket +import time +import board +import simpleio +import adafruit_vl53l4cd +from adafruit_seesaw import seesaw, rotaryio, neopixel +from adafruit_seesaw.analoginput import AnalogInput + +# VL53L4CD setup +vl53 = adafruit_vl53l4cd.VL53L4CD(board.I2C()) + +# rotary encoder setup +encoder = seesaw.Seesaw(board.I2C(), addr=0x36) +encoder.pin_mode(24, encoder.INPUT_PULLUP) +rot_encoder = rotaryio.IncrementalEncoder(encoder) + +# neoslider setup - analog slide pot and neopixel +# 0x30 = red control +# 0x31 = green control +# 0x32 = blue control +red_slider = seesaw.Seesaw(board.I2C(), 0x30) +red_pot = AnalogInput(red_slider, 18) +r_pix = neopixel.NeoPixel(red_slider, 14, 4) + +g_slider = seesaw.Seesaw(board.I2C(), 0x31) +green_pot = AnalogInput(g_slider, 18) +g_pix = neopixel.NeoPixel(g_slider, 14, 4) + +b_slider = seesaw.Seesaw(board.I2C(), 0x32) +blue_pot = AnalogInput(b_slider, 18) +b_pix = neopixel.NeoPixel(b_slider, 14, 4) + +# rotary encoder position tracker +last_position = 0 + +# neoslider position trackers +last_r = 0 +last_g = 0 +last_b = 0 + +# VL53L4CD value tracker +last_flight = 0 + +# rotary encoder index +x = 0 + +# VL53L4CD start-up +vl53.inter_measurement = 0 +vl53.timing_budget = 200 + +vl53.start_ranging() + +# HTTP socket setup +s = socket.socket() +print("socket check") + +port = 12345 + +s.bind(('', port)) +print("socket binded to %s" %(port)) + +s.listen(1) +print("listening") + +time.sleep(10) + +c, addr = s.accept() +print('got connected', addr) + +while True: + # rotary encoder position read + position = -rot_encoder.position + + # VL53L4CD distance read + flight = vl53.distance + + # mapping neosliders to use 0-255 range for RGB values in Processing + r_mapped = simpleio.map_range(red_pot.value, 0, 1023, 0, 255) + g_mapped = simpleio.map_range(green_pot.value, 0, 1023, 0, 255) + b_mapped = simpleio.map_range(blue_pot.value, 0, 1023, 0, 255) + + # converting neoslider data to integers + r_pot = int(r_mapped) + g_pot = int(g_mapped) + b_pot = int(b_mapped) + + # rotary encoder position check + if position != last_position: + # rotary encoder is ranged to 0-3 + if position > last_position: + x = (x + 1) % 4 + if position < last_position: + x = (x - 1) % 4 + # send rotary encoder value over socket + # identifying string is "enc" + c.send(str.encode(' '.join(["enc", str(x)]))) + # reset last_position + last_position = position + # sliders only update data for changes >15 to avoid flooding socket + # red neoslider position check + if abs(r_pot - last_r) > 15: + # send red neoslider data over socket + # identifying string is "red" + c.send(str.encode(' '.join(["red", str(r_pot)]))) + # reset last_r + last_r = r_pot + # green neoslider position check + if abs(g_pot - last_g) > 15: + # send green neoslider data over socket + # identifying string is "green" + c.send(str.encode(' '.join(["green", str(g_pot)]))) + # reset last_g + last_g = g_pot + # blue neoslider position check + if abs(b_pot - last_b) > 15: + # send blue neoslider data over socket + # identifying string is "blue" + c.send(str.encode(' '.join(["blue", str(b_pot)]))) + # reset last_b + last_b = b_pot + # VL53L4CD value check + if abs(flight - last_flight) > 2: + # setting max value of 45 + if flight > 45: + flight = 45 + # send VL53L4CD data over socket + # identifying string is "flight" + c.send(str.encode(' '.join(["flight", str(flight)]))) + # reset last_flight + last_flight = flight + # set neopixels on neosliders to match background color of Processing animations + r_pix.fill((r_pot, g_pot, b_pot)) + g_pix.fill((r_pot, g_pot, b_pot)) + b_pix.fill((r_pot, g_pot, b_pot)) + # reset the VL53L4CD + vl53.clear_interrupt() + \ No newline at end of file diff --git a/Raspberry_Pi_Video_Synth/ProcessingRaspberryPiVideoSynth.pde b/Raspberry_Pi_Video_Synth/ProcessingRaspberryPiVideoSynth.pde new file mode 100644 index 000000000..cadccae5e --- /dev/null +++ b/Raspberry_Pi_Video_Synth/ProcessingRaspberryPiVideoSynth.pde @@ -0,0 +1,261 @@ +// SPDX-FileCopyrightText: 2022 Liz Clark for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +// Processing library for Networking +// make sure that you have the library installed! +import processing.net.*; + +// HTTP client +Client myClient; + +// variables for receiving data from Blinka socket +int index; +String inString; + +// holding the red, green, blue data +String[] r; +String[] g; +String[] b; +int red; +int green; +int blue; + +// holding the VL53L4CD data +String[] f; +int flight; + +// cat and pizza images +//emojis are from the OpenMoji emoji library (https://openmoji.org/) +PImage cat_img; +PImage pizza_img; + +// colors for Circles animation +color c_red = color(255, 0, 0); +color c_green = color(0, 255, 0); +color c_blue = color(0, 0, 255); +color c_yellow = color(255, 125, 0); +color c_aqua = color(0, 125, 255); +color c_purple = color(255, 0, 255); + +IntList colors; + +// float for Cube animation +float i = 0.0; + +// variables for Circles animation +int rad = 60; +float xpos, ypos; + +float xspeed = 2.8; +float yspeed = 10; + +int xdirection = 1; +int ydirection = 1; + +// variables for pizzaCat animation +float pizza_speed = 20; +float cat_speed = 30; + +float pizza_pos, cat_pos; + +int img_w = 10; + +int pizza_dir = 1; +int cat_dir = 1; +int num_cats; + +// variables for dancingTriangles animation +int x1; +int y1; +int x2; +int y2; +int x3; +int y3; + +void setup() +{ + // setting animations to run fullscreen with P3D + fullScreen(P3D); + // RGB color mode with value range of 0-255 + colorMode(RGB, 255); + ellipseMode(RADIUS); + // setting xpos and ypos in center + xpos = width/2; + ypos = height/2; + + // creating array of colors + // this is used for the Circles animation + colors = new IntList(); + colors.append(c_red); + colors.append(c_yellow); + colors.append(c_green); + colors.append(c_aqua); + colors.append(c_blue); + colors.append(c_purple); + + // loading the cat and pizza images + cat_img = loadImage("cat.png"); + pizza_img = loadImage("pizza.png"); + + // connecting to socket to communicate with Blinka script + myClient = new Client(this, "127.0.0.1", 12345); + +} + +// void draw() is the loop in Processing +void draw() +{ + //if data is coming in over the socket... + if (myClient.available() > 0) { + //string data is stored in inString + inString = myClient.readString(); + //if the string begins with 'enc' + //aka is a msg from the rotary encoder... + if (inString.startsWith("enc")) { + // the encoder pos is stored in index + String[] q = splitTokens(inString); + index = int(q[1]); + } + //if the string begins with 'red' + //aka is from the red neoslider + if (inString.startsWith("red")) { + //the red value is stored in red + String[] r = splitTokens(inString); + red = int(r[1]); + } + //if the string begins with 'green' + //aka is from the green neoslider + if (inString.startsWith("green")) { + // the green value is stored in green + String[] g = splitTokens(inString); + green = int(g[1]); + } + //if the string begins with 'blue' + //aka is from the blue neoslider + if (inString.startsWith("blue")) { + //the blue value is stored in blue + String[] b = splitTokens(inString); + blue = int(b[1]); + } + //if the string begins with flight + //aka is from the VL53L4CD + if (inString.startsWith("flight")) { + //the time of flight value is stored in flight + String[] f = splitTokens(inString); + flight = int(f[1]); + } + } + //the encoder's position corresponds with which animation plays + if (index == 0) { + circles(); + } + + if (index == 1) { + cube(); + } + if (index == 2) { + dancingTriangles(); + } + if (index == 3) { + pizzaCat(); + } + } + +//the Circles animation +//colorful circles randomly appear in the middle of the screen +//background color is affected by the sliders +//the circles' size is affected by the VL53L4CD +void circles() { + background(red, green, blue); + strokeWeight(1); + + ypos = ypos + ( yspeed * ydirection ); + + if (ypos > height-rad || ypos < rad) { + ydirection *= +1; + } + + int size = int(map(flight, 0, 45, 300, 25)); + + for (int i = 0; i < 10; i++) { + for (int z = 0; z < 6; z++) { + fill(colors.get(z)); + circle(width/2, random(ypos), random(size)); + } + } +} + +//the Cube animation +//a 3D cube spins in the center of the screen +//background color is affected by the sliders +//the speed of the spinning cube is affected by the VL53L4CD +void cube() { + strokeWeight(5); + + float speed = map(flight, 0, 45, 10, 0.1); + + background(red, green, blue); + translate(width/2, height/2, 0); + + i = i + speed; + if (i > 180) { + i = 0.0; + } + rotateY(radians(i)); + noFill(); + box(500); +} + +//the Pizza Cat animation +//pizza and cat face emojis go back and forth across the screen +//emojis are from the OpenMoji emoji library (https://openmoji.org/) +//the background color is affected by the sliders +//the speed of the cat emojis are affected by the V53L4CD +void pizzaCat() { + background(red, green, blue); + int num_cats = int(map(flight, 0, 45, 65, 15)); + + pizza_pos = pizza_pos + ( pizza_speed * pizza_dir ); + cat_pos = cat_pos + ( num_cats * cat_dir ); + + if (pizza_pos + img_w > width || pizza_pos < img_w) { + pizza_dir *= -1; + } + if (cat_pos + img_w > height || cat_pos < img_w) { + cat_dir *= -1; + } + + for (int p = 0; p < 25; p++) { + image(cat_img, pizza_pos-10, cat_pos*p); + image(pizza_img, pizza_pos*p, cat_pos+10); + } +} + +// the dancingTriangles animation +// triangles are randomly generated in the center of the screen +//the background is affected by the sliders +// the speed of new triangles being added are affected by the V53L4CD +void dancingTriangles() { + int speed = int(map(flight, 0, 45, 25, 100)); + + background(red, green, blue); + strokeWeight(30); + + for (int w = 800; w < 1000; w ++) { + for (int h = 1100; h < 1500; h++) { + + x1 = int(random(h)); + y1 = int(random(w)); + + x2 = int(random(h)); + y2 = int(random(w)); + + x3 = int(random(h)); + y3 = int(random(w)); + } + } + noFill(); + triangle(x1, y1, x2, y2, x3, y3); + delay(speed); +} diff --git a/Raspberry_Pi_Video_Synth/cat.png b/Raspberry_Pi_Video_Synth/cat.png new file mode 100644 index 000000000..47119979e Binary files /dev/null and b/Raspberry_Pi_Video_Synth/cat.png differ diff --git a/Raspberry_Pi_Video_Synth/pizza.png b/Raspberry_Pi_Video_Synth/pizza.png new file mode 100644 index 000000000..508c40792 Binary files /dev/null and b/Raspberry_Pi_Video_Synth/pizza.png differ