Sensing light gradient (arduino + processing)
in
Share your Work
•
1 month ago
This is preliminary work part of something bigger. The Arduino, with 4 phtoresistors, was used to detect variation across a gradient of light/shade. The direction and angle of maximum/minimum light is calculated using a technique called Wombling (for the mathematically inclined it is just using a bilinear interpolation and differentiating to get the gradient magnitude and direction).
Then via serial communication with processing to draw the corresponding arrow (but the idea is to use it for far more interesting interactions)
Code (Arduino side)
- /*Light gradient detector
- Tomas de-Camino-Beck
- detects de direction of the dark/brigth side
- using 4 photoresistors
- configured in a square,
- top: A1, A3
- bottom: A0, A2
- */
- #include <math.h>
- int s1,s2,s3,s4;
- int min = 0;
- int max = 0;
- int switchState = 0;
- float dx = 0;
- float dy = 0;
- void setup()
- {
- Serial.begin(9600);
- //push button for calibration
- pinMode(8,INPUT);
- }
- void loop(){
- switchState = digitalRead(8);
- if(switchState==0){
- //get the readings
- s1 = getValue(A0);
- s2 = getValue(A1);
- s3 = getValue(A2);
- s4 = getValue(A3);
- //calculate x and y direction gradients
- dx = s4 - s3 + 0.5*(s3 - s4 + s2 - s1);
- dy = s1 - s3 + 0.5*(s3 - s4 + s2 - s1);
- //Calculation of magnitude and angle to send over serial
- //magnitude
- Serial.print(sqrt(square(dx)+square(dy)));
- Serial.print(",");
- //angle in radians
- Serial.println(atan2(dx,dy));
- }
- //calibrate light conditions pressing the button
- //send 0s in the meantime
- else {
- calibrate();
- Serial.println("0,0");
- }
- delay(50);
- }
- //Calibrate light conditions using A0 and A3
- //Press the button an cover sensor A3
- void calibrate(){
- int l0 =analogRead(A0);
- int l1 =analogRead(A3);
- if(l0>max){
- max = l0;
- }
- if(l1<min){
- min = l1;
- }
- }
- //function that maps to a more stable scale
- int getValue(int pin){
- int val = analogRead(pin);
- val = map(val,min,max,0,255);
- val = constrain(val,0,255);
- return(val);
- }
- //Tomas de Camino Beck
- import processing.serial.*;
- Serial port;
- // magnitude [0] and angle in radians [1]
- float[] coord = new float[2];
- String data="0,0";
- PFont angulo;
- void setup()
- {
- size(700, 700);
- println(Serial.list());
- port = new Serial(this, Serial.list()[0], 9600);
- port.clear();
- port.bufferUntil(' ');
- ellipseMode(CENTER);
- background(255);
- angulo = createFont("Times",30,true);
- textFont(angulo,30);
- }
- void draw()
- {
- smooth(8);
- strokeWeight(4);
- background(0);
- noFill();
- stroke(255,int(coord[0])+100);
- arrow(width/2,height/2,coord[0]*2,coord[1]);
- ellipse(width/2,height/2,coord[0]*4+2,coord[0]*4+2);
- stroke(255,150);
- if(coord[1]>=0){
- arc(width/2,height/2,50,50,0,coord[1],PIE);
- textAngle(coord[1]);
- } else{
- arc(width/2,height/2,50,50,0,TWO_PI+coord[1],PIE);
- textAngle(TWO_PI+coord[1]);
- }
- }
- void serialEvent(Serial port) {
- //data = port.readStringUntil(' ');
- data = port.readString();
- coord = float(split(data,','));
- }
- void arrow(int x, int y, float l, float ang){
- //para determinar el largo de la punta en 45 grados
- int arrowLength = 8;
- pushMatrix();
- //cambia el eje del dibujo y lo rota
- translate(x, y);
- rotate(ang);
- //dibuja una linea y flecha en el eje X
- line(0,0,l, 0);
- line(l, 0, l - arrowLength, -arrowLength);
- line(l, 0, l - arrowLength, arrowLength);
- text(nf(int(l),0,0),l+10,0);
- popMatrix();
- }
- void textAngle(float ang){
- fill(255,200);
- pushMatrix();
- translate(width/2,height/2);
- rotate(ang*0.5);
- text(nf(int(degrees(ang)),0,0),30,0);
- popMatrix();
- }