Hi! I am trying to use flex sensors to change the position of a drawing in processing.
I got one of the flex sensors to work and move the drawing, but it moves all the parts of the drawing that should be controlled by different flex sensors, and I don’t know how to make multiple sensors move different things in the processing code.
You are probably sending the value over with Serial, right? Then you just need to send all the values from the different sensors with delimiters and assign different variables to them respectively.
Example :
Arduino :
int values[3];
void setup() {
//initialize serial communications at a 9600 baud rate
Serial.begin(9600);
}
void loop() {
values[0] = analogRead(A0);
values[1] = analogRead(A1);
values[2] = analogRead(A2);
//the individual sensors values
Serial.println(value[0] + "split" + value[1] + "split" + value[2]);
//you can use any char/String as a delimiter
delay(100);
}
Processing :
Serial myPort;
String val; // Data received from the serial port
int[] intVals;
void setup() {
String portName = Serial.list()[0]; //change the 0 to match your port
myPort = new Serial(this, portName, 9600);
}
void draw() {
if ( myPort.available() > 0) { // If data is available,
val = myPort.readStringUntil('\n'); // read it and store it in val
}
intVals = int(split(val, "split"));
//you can use splitTokens(val, delimiters) to split on multiple token.
println(val, intVals); //print it out
}
Thank you!
I have a problem with the arduino code, it tells me that it expects an unqualified id before the “[” that is after int on the first line of code.
I am also confused as to where in the processing code would I put the variable that moves the drawing?
this is my code in processing:
import processing.serial.*;
Serial myPort;
float t;
int bodyFill, bodyEdge;
int[] serialInArray = new int[3];
int serialCount = 0;
FingerPart[] finger;
Hand hand;
public void setup() {
println("Available serial ports:");
println(Serial.list());
myPort =
//new Serial(this, Serial.list()[0], 9600);
new Serial(this,"/dev/tty.usbmodem14201", 9600);
size(500, 630);
bodyFill = color(#CFAB91);
bodyEdge = color(#A78369);
hand = new Hand(100, 60, 250, 250, 0);
FingerPart p0, p1, p2;
Finger f;
//Index Finger
//t= serialInArray[0];
p2 = new FingerPart(50, 10, 40, 0, 0, PI/3);
p1 = new FingerPart(80, 12, 68, 0, 0, PI/3);
p0 = new FingerPart(100, 14, 86, 0, 0, PI/5);
p0.nextPart = p1;
p1.nextPart = p2;
f = new Finger(p0);
hand.addFinger(f, 40, -10);
//Middle Finger
//t= serialInArray[1];
p2 = new FingerPart(30, 10, 20, 0, 0, PI/2.8);
p1 = new FingerPart(60, 12, 48, 0, 0, PI/2.8);
p0 = new FingerPart(80, 14, 66, 0, 0, PI/4.7);
p0.nextPart = p1;
p1.nextPart = p2;
f = new Finger(p0);
hand.addFinger(f, 40, -10);
// Opposing thumb
//t= serialInArray[2];
p1 = new FingerPart(40, 14, 26, 0, 0, -PI/3);
p0 = new FingerPart(50, 16, 34, 0, PI/2, PI/8);
p0.nextPart = p1;
f = new Finger(p0);
hand.addFinger(f, 16, 16);
}
public void draw() {
background(64);
noStroke();
fill(227, 230, 255);
rect(0, 500, width, height-500);
hand.display();
}
/**
* This represents one section of a finger.
*/
public class FingerPart {
// Next section of the finger (order is from hand to finger tip)
FingerPart nextPart = null;
// The pivot point for the next section
float pivotX = 0;
float pivotY = 0;
// The range of angles this part can be made relative
// to its parent shape.
float startAngle = 0;
float endAngle = TWO_PI;
// Finger dimensions
float length;
float thick;
/**
* Create a finger part. <br>
* The nextPart (finger section) is set later.
*/
public FingerPart(float len, float th, float px, float py, float sang, float eang) {
length = len;
thick = th;
pivotX = px;
pivotY = py;
startAngle = sang;
endAngle = eang;
}
/**
* Display the finger at an angle determined by the parameter t which
* should be in the range 0-1 and corresponds to an angle in the range <br>
* startAngle (t=0) to endAngle (t=1) <br>
* Notice that this will call the display method for the next finger
* section and so on.
*/
public void display(float t) {
pushMatrix();
rotate(startAngle + (endAngle - startAngle) * t);
ellipse(0, 0, 2 * thick, 2 * thick);
ellipse(pivotX, pivotY, 2 * thick, 2 * thick);
noStroke();
rect(0, -thick, pivotX, 2 * thick);
stroke(bodyEdge);
line(0, -thick, pivotX, -thick);
line(0, thick, pivotX, thick);
translate(pivotX, pivotY);
if (nextPart != null)
nextPart.display(t);
popMatrix();
}
}
/**
* This represents a single finger. <br>
* It has its own t value so it can be moved independently of the other
* fingers.
*/
public class Finger {
// The first section of the finger
FingerPart first;
// Its position relative to the hand.
float posX;
float posY;
// Controls angle the finger is drawn at
float t;
/**
* Create a finger specifying the first finger section
*/
public Finger(FingerPart part) {
first = part;
}
/**
* Drawing the first section will cause subsequent sections
* to be displayed.
*/
public void display() {
pushMatrix();
translate(posX, posY);
if (first != null)
first.display(t);
popMatrix();
if (myPort.available() >0){
t = myPort.read();
}
}
}
/**
* The hand can have as many fingers as you like. <br>
* Calling the display method will draw the hand
* and then each finger (which then displays the
* finger sections. <br>
*/
public class Hand {
ArrayList<Finger> fingers = new ArrayList<Finger>();
float posX;
float posY;
float angle;
float length;
float thick;
public Hand(float len, float th, float px, float py, float ang) {
length = len;
thick = th;
posX = px;
posY = py;
angle = ang;
}
public void addFinger(Finger f, float x, float y) {
f.posX = x;
f.posY = y;
fingers.add(f);
}
/**
* Move the specified finger
* @param id the position in the arraylist
* @param t the angle control value
*/
public void moveFinger(int id, float t) {
if (id >= 0 && id < fingers.size())
fingers.get(id).t = t;
}
/**
* Display the hand at its current position and angle.
* @param t
*/
public void display() {
pushStyle();
fill(bodyFill);
stroke(bodyEdge);
strokeWeight(2);
pushMatrix();
translate(posX, posY);
rotate(angle);
rect(-length / 2, -thick/2, length, thick);
fill(bodyFill);
for (Finger f : fingers)
f.display();
popMatrix();
popStyle();
}
}
Indeed, i made a mistake in the arduino code. Although it‘s similar to processing there are some differences in the syntax .
I fixed it, and now it should work.
As for where to put the variable? What do you mean by that? Which variable?
You should listen to the Serial Input and set your intVals[] to the resulting values in draw. You could also use a Serial Event, but that‘s not really neccessary in your case i think…
And then, just use the intVals[] to set maybe the position of individual fingerparts or something like that… as for how to do that, you‘d want to create a new Global method and call it in draw(), to keep it clean (not having 300+ lines in draw…).
And within that method, you just do something like this :
for (int i = 0; i < serialInArray.length; i++) {
hand.getFinger(floor(i/3)).getFingerPart(i%3).setAngle(serialInArray[i]);
}
//this would loop through multiple fingers with each having 3 Finger parts
//and set their angle to be the corresponding intVals value.
//in your case though it‘s better to just get and set them manually, not in a for loop (cause you only have 3 Inputs for now, so not worth it)
//you could also use (floor(i/5)) to get to the next Hand when one is done, because 5 fingers per Hand...
//though you‘d have to start with body.getHand(floor(i/5)).getF...
//or in your case the Code would be ~ this
for (int i = 0; i < serialInArray.length; i++) {
hand.moveFingers(i, serialInArray[i]);
}
//though i didn‘t check if these methods really work Right, if they do what they look like they’re supposed to do, then this is how it should go well.
}
also check out
https://processing.org/reference/libraries/serial/serialEvent_.html
Example
import processing.serial.*;
Serial myPort;
String data; // latest arduino line
// rev
int[] datos; // as array of integers
StringList list; // stored lines
int listlong = 18; // many
int w= 640, h = 360; // canvas settings
void setup_serial() { // USB arduino..
printArray(Serial.list());
String portName = Serial.list()[1]; // adjust 0.. x port
myPort = new Serial(this, portName, 9600);
myPort.clear();
myPort.bufferUntil('\n');
println("try connect to "+portName);
}
void serialEvent(Serial p) { // handle serial data
data = trim(p.readStringUntil('\n'));
if (data != null) {
println(data); // print every GOOD line
datos = int( split(data, ",") ); // create int array (unused example )
list.append( data ); // OR store line as String list
if ( list.size() >= listlong ) list.remove(0); // erase the oldest? // for ( int i = 0; i<list.size(); i++ ) print(i+"_"+ list.get(i) ); println();
}
}
void settings() {
size(w, h);
}
void setup() {
list = new StringList();
setup_serial();
}
void draw() {
background(0, 0, 80);
for ( int i = 0; i<list.size(); i++ ) text( list.get(i), 10, 20+i*20 ); // running list of arduino lines
}
It is still incorrect.
Corrections to code you provided and also tested and working:
Arduino:
int value[3];
int count;
void setup()
{
Serial.begin(9600);
}
void loop()
{
//value[0] = analogRead(A0);
// value[1] = analogRead(A1);
//value[2] = analogRead(A2);
//Test values
value[0] = count;
value[1] = count+10;
value[2] = count+20;
count++;
Serial.println(String(value[0]) + "split" + String(value[1]) + "split" + String(value[2]));
delay(100);
}
Processing:
import processing.serial.*;
Serial myPort;
String val;
void setup()
{
printArray(Serial.list());
String portName = Serial.list()[2];
myPort = new Serial(this, portName, 9600);
}
void draw()
{
if ( myPort.available() > 0)
{
val = myPort.readStringUntil('\n');
if (val!= null)
{
val = trim(val);
intVals = int(split(val, "split"));
println(val);
printArray(intVals);
}
}
}
Indeed, thanks. I missed the s at the end of value‘s‘