arduino - Using a distance sensor in Processing to control the attributes of shapes -
i'm trying make program use readings gets distance sensor control attributes of circles (size, xy , colour). i'm trying make record current value , apply value when press relevant key (eg. press 's' , changes size whatever distance @ point). - ideally i'd circle change whatever field next dynamically move hand on sensor, seems bit beyond me.
i've tried as can, i'm not sure of i've commented out. tips or advice? i'm not sure i'm doing when comes classes , constructors.
edit: when run code, nothing happens.
import processing.serial.*; int xpos, ypos, s, r, g, b; circle circle; int shapesize, distance; string comportstring; serial myport; void setup(){ size(displaywidth,displayheight); //use entire screen size. //open serial port communication arduino myport = new serial(this, "/dev/cu.usbmodem1411", 9600); myport.bufferuntil('\n'); // trigger serialevent on new line } void draw(){ background(0); delay(50); //delay used refresh screen println(distance); } void serialevent(serial cport){ comportstring = (new string(cport.readbytesuntil('\n'))); if(comportstring != null) { comportstring=trim(comportstring); /* use distance received arduino modify y position of first square (others follow). should match code settings on arduino. in case 200 maximum distance expected. distance mapped value between 1 , height of screen */ distance = int(map(integer.parseint(comportstring),1,200,1,height)); if(distance<0){ /*if computer receives negative number (-1), sensor reporting "out of range" error. convert of these distance of 0. */ distance = 0; } } } void keypressed() { // n new circle (and keep old one) if((key == 'n') || (key == 'n')) { println("n"); circle = new circle(1,1,1,1,1,1); } //r - change red if((key == 'r') || (key == 'r')) { float red = map(distance, 0, 700, 0, 255); r = int(red); println("r " + r); } //g - change green if((key == 'g') || (key == 'g')) { float green = map(distance, 0, 700, 0, 255); g = int(green); println("g " + g); } //b - change blue if((key == 'b') || (key == 'b')) { float blue = map(distance, 0, 700, 0, 255); b = int(blue); println("b " + b); } //s - change size if((key == 's') || (key == 's')) { s = distance; println("s " + s); } //x - change x pos if((key == 'x') || (key == 'x')) { xpos = distance; println("x " + xpos); } //y - change y pos if((key == 'y') || (key == 'y')) { ypos = distance; println("y " + ypos); } } class circle { circle(int xpos, int ypos, int s, int r, int g, int b){ ellipse(xpos, ypos, s, s); color(r, g, b); } int getx(){ return xpos; } int gety(){ return ypos; } }
i split steps/tasks:
- connecting arduino
- reading values arduino
- mapping read values
- controlling mapping
you've got arduino part pretty there, things messy when trying map read values circle on screen. now, simplicity reasons, let's ignore classes , focus on drawing single ellipse x,y,size,r,g,b properties.
to read of jitter should update property ellipse continuously, not when pressing key. on key event should change property gets updated. use variables keep track of ellipse properties you're updating.
here's refactored version of code based on points above:
import processing.serial.*; int xpos,ypos,s,r,g,b; int distance; int propertyid = 0;//keep track of property should updated on distance int prop_xpos = 0; int prop_ypos = 1; int prop_s = 2; int prop_r = 3; int prop_g = 4; int prop_b = 5; void setup(){ size(400,400); //setup defaults see on screen xpos = ypos = 200; s = 20; r = g = b = 127; //initialize arduino - search port based on osx name string[] portnames = serial.list(); for(int = 0 ; < portnames.length; i++){ if(portnames[i].contains("usbmodem")){ try{ serial arduino = new serial(this,portnames[i],9600); arduino.bufferuntil('\n'); return; }catch(exception e){ showserialerror(); } } } showserialerror(); } void showserialerror(){ system.err.println("error connecting arduino!\nplease check usb port"); } void draw(){ background(0); fill(r,g,b); ellipse(xpos,ypos,s,s); } void serialevent(serial arduino){ string rawstring = arduino.readstring();//fetch raw string if(rawstring != null){ string trimmedstring = rawstring.trim();//trim raw string int rawdistance = int(trimmedstring);//convert integer distance = (int)map(rawdistance,1,200,1,height); updatepropsondistance();//continously update circle properties } } void updatepropsondistance(){ if(propertyid == prop_xpos) xpos = distance; if(propertyid == prop_ypos) ypos = distance; if(propertyid == prop_s) s = distance; if(propertyid == prop_r) r = distance; if(propertyid == prop_g) g = distance; if(propertyid == prop_b) b = distance; } void keyreleased(){//only change proprty changes on key press if(key == 'x' || key == 'x') propertyid = prop_xpos; if(key == 'y' || key == 'y') propertyid = prop_ypos; if(key == 's' || key == 's') propertyid = prop_s; if(key == 'r' || key == 'r') propertyid = prop_r; if(key == 'g' || key == 'g') propertyid = prop_g; if(key == 'b' || key == 'b') propertyid = prop_b; } //usually idea test - in case use mousey instead of distance sensor void mousedragged(){ distance = mousey; updatepropsondistance(); }
if makes sense, can encapsulated in class. use array store properties, if props[0] x, props1 y, etc. harder read, use intdict allows index values based on string instead of value (so can props["x"]
instead of props[0]
).
here's encapsulated version of code:
import processing.serial.*; circle circle = new circle(); void setup(){ size(400,400); //initialize arduino - search port based on osx name string[] portnames = serial.list(); for(int = 0 ; < portnames.length; i++){ if(portnames[i].contains("usbmodem")){ try{ serial arduino = new serial(this,portnames[i],9600); arduino.bufferuntil('\n'); return; }catch(exception e){ showserialerror(); } } } showserialerror(); } void showserialerror(){ system.err.println("error connecting arduino!\nplease check usb port"); } void draw(){ background(0); circle.draw(); } void serialevent(serial arduino){ string rawstring = arduino.readstring(); if(rawstring != null){ string trimmedstring = rawstring.trim(); int rawdistance = int(trimmedstring); int distance = (int)map(rawdistance,1,200,1,height); circle.update(distance); } } void keyreleased(){ circle.setupdateproperty(key+"");//update circle property based on key gets pressed. +"" quick way make string char } //usually idea test - in case use mousey instead of distance sensor void mousedragged(){ circle.update(mousey); } class circle{ //an intdict (integer dictionary) associative array instead of accessing values integer index (e.g. array[0] //you access them string index (e.g. array["name"]) intdict properties = new intdict(); string updateproperty = "x";//property update circle(){ //defaults properties.set("x",200); properties.set("y",200); properties.set("s",20); properties.set("r",127); properties.set("g",127); properties.set("b",127); } void draw(){ fill(properties.get("r"),properties.get("g"),properties.get("b")); ellipse(properties.get("x"),properties.get("y"),properties.get("s"),properties.get("s")); } void setupdateproperty(string prop){ if(properties.haskey(prop)) updateproperty = prop; else{ println("circle not contain property: " + prop+"\navailable properties:"); println(properties.keyarray()); } } void update(int value){ properties.set(updateproperty,value); } }
in both examples can test distance value dragging mouse on y axis.
regarding hc-sr04 sensor, can find code on arduino playground distance in cm. haven't used sensor myself yet, notice other people has issues it, it's worth checking this post well. if want roll own arduino code, no problem, can use hc-sr04 datasheet(pdf link) formula:
formula: / 58 = centimeters or / 148 =inch; or: range = high level time * velocity (340m/s) / 2; suggest use on 60ms measurement cycle, in order prevent trigger signal echo signal.
it's important accurate values (you'll avoid jitter when using these draw in processing). additionally can use easing or moving average.
here's basic moving average example:
int historysize = 25;//remember number of past values int[] x = new int[historysize]; int[] y = new int[historysize]; void setup(){ size(400,400); background(255); nofill(); } void draw(){ //draw original trails in red stroke(192,0,0,127); ellipse(mousex,mousey,10,10); //compute moving average float avgx = average(x,mousex); float avgy = average(y,mousey); //draw moving average in green stroke(0,192,0,127); ellipse(avgx,avgy,10,10); } void mousereleased(){ background(255); } float average(int[] values,int newvalue){ //shift elements 1, last 2nd: count backwards float total = 0; int size = values.length; for(int = size-1; > 0; i--){//count backwards values[i] = values[i-1];//copy previous value current total += values[i];//add values total } values[0] = newvalue;//add newest value @ start of list total += values[0];//add latest value total return (float)total/size;//return average }
Comments
Post a Comment