The photoresistor responds to changes in ambient light as my hand moves up and down. The Arduino sends the reading to a Processing sketch on the computer via a Serial command (through the USB cable). The processing sketch interprets the signal from the Arduino and selects the appropriate picture to display.
I took a series of screenshots from the following YouTube video: http://www.youtube.com/watch?v=h6nE8m74kDg And after borrowing a bit of code from these sites (1,2), the project was born.
This idea is not new, nor my own. There are many people who have done this project before, but I thought to blog about how I have done it, just for fun.
The Project Movie
Components Required
- Arduino Uno (and associated software), and USB cable
- Photoresistor or Photocell
- 10K resistor
- Wires to put it all together
- Processing IDE from http://processing.org
- Computer/laptop
The Arduino Sketch
The Arduino Code:
You can download the Arduino IDE from this site.1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | /* Jumper: Using an Arduino to animate: Written by ScottC on 02/06/2012 */ int photoRPin = 0; int minLight; int maxLight; int lightLevel; int adjustedLightLevel; int oldLightLevel; void setup() { Serial.begin(9600); //Setup the starting light level limits lightLevel=analogRead(photoRPin); minLight=lightLevel-10; maxLight=lightLevel; oldLightLevel=lightLevel; } void loop(){ lightLevel=analogRead(photoRPin); delay(10); //auto-adjust the minimum and maximum limits in real time if(minLight>lightLevel){ minLight=lightLevel; } if(maxLight<lightLevel){ maxLight=lightLevel; } //Map the light level to produce a result between 1 and 28. adjustedLightLevel = map(lightLevel, (minLight+20), (maxLight-20), 1, 28); adjustedLightLevel = constrain (adjustedLightLevel, 1,28); /*Only send a new value to the Serial Port if the adjustedLightLevel value changes.*/ if(oldLightLevel==adjustedLightLevel){ //do nothing if the old value and the new value are the same. }else{ //Update the oldLightLevel value for the next round oldLightLevel=adjustedLightLevel; /*Send the adjusted Light level result to Serial port (processing)*/ Serial.println(adjustedLightLevel); } } |
The code above was formatted using this site.
The Processing Code:
You can download the Processing IDE from this site.1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | /* Jumper: Using an Arduino to animate Written by ScottC on 02/06/2012 Source code derived from : http://processing.org/learning/topics/sequential.html http://processing.org/discourse/beta/num_1267080062.html Pictures captured from: http://www.youtube.com/watch?v=h6nE8m74kDg ======================================================= */ import processing.serial.*; Serial myPort; String sensorReading=""; // Create the array that will hold the images PImage[] movieImage = new PImage[29]; /* The frame variable is used to control which image is displayed */ int frame = 1; /* Setup the size of the window. Initialise serial communication with Arduino and pre-load the images to be displayed later on. This is done only once. I am using COM6 on my computer, you may need replace this value with your active COM port being used by the Arduino.*/ void setup(){ size(700,600); myPort = new Serial(this, "COM6", 9600); myPort.bufferUntil('\n'); for(int i=0;i<28;i++){ movieImage[i] = loadImage("Jumper" + (i+1) + ".jpg"); } } // The draw function controls the animation sequence. void draw(){ //this draws the relevant image to the window image(movieImage[frame-1],0,0,width,height); } void serialEvent (Serial myPort){ sensorReading = myPort.readStringUntil('\n'); if(sensorReading != null){ sensorReading=trim(sensorReading); if (sensorReading.length()<2){ frame = integerFromChar(sensorReading.charAt(0)); }else{ frame = integerFromChar(sensorReading.charAt(0))*10; frame += integerFromChar(sensorReading.charAt(1)); } } } /* This function used to convert the character received from the serial port (Arduino), and converts it to a number */ int integerFromChar(char myChar) { if (myChar < '0' || myChar > '9') { return -1; }else{ return myChar - '0'; } } |
The code above was formatted using this site.
hello. i want to submit this as my 1st arduino project in my versity. i need your help please can you give me instruction to complete the task my email address is : arif.iqbal04@gmail.com
ReplyDeleteAm not sure what instructions you need? The instructions for this project are located above your comment.
DeleteWhy do I get the line
ReplyDeletesensorReading = myPort.readStringUntil('\n');
.. as an error?
It says The function readStringUntil(char) does not exist.
This is a problem with the new version of Processing:
DeletesensorReading = (new String(myPort.readBytesUntil('\n')));
very nice
ReplyDeleteThanks
DeleteNice i'm so excited to try this! Thank you for sharing
ReplyDeletehey, I don't understand your if statements in the processing code could you please explain them to me more in depth.
ReplyDeleteIf the sensor reading characters are equal to a number less than 10, it has a length < 2, so then just use that character and convert it to a number. This number becomes the frame number. eg Character "5" becomes the number 5.
DeleteIf the sensor reading string is greater than 10, it will be a double digit number.
So lets say the sensorReading is "17".
The character at index of 0 = 1
The character at index of 1 = 7
So these two lines:
frame = integerFromChar(sensorReading.charAt(0))*10;
frame += integerFromChar(sensorReading.charAt(1));
would first multiply 1 by 10 = 10
then add 7 to make it a "number" which has a value of 17.
So the variable "frame" would become 17.
I don't know why I did it this way - it was a long time ago.
It may have been a limitation of the software at that time ??
I would think that you could just convert the string "17" directly to an integer 17 with the current version of software.
But anyway - that is what the if statements are trying to do.
Thank You! That explains a lot. Also what is the first line of code trying to do in first line in void draw meant to do?
ReplyDelete//this draws the relevant image to the window
Deleteimage(movieImage[frame-1],0,0,width,height);
movieImage[] is an array of image names.
DeleteYou draw the image to the screen using the image() command.
The image command takes the following parameters:
image("Image file location.jpg", X,Y,width, height);
So in the line you asked about, it takes the image location from the movieImage array designated by the frame variable, and displays it at location (0,0), with a width designated by the width variable, and height designated by the height variable.
Hey, I thought it was the int integerFromChar that converted the string to integer but after reading the comment you said it was the if statements that are trying to do that? So I was confused as to what the last int part of the code does?
ReplyDeleteThe if statements use that function "integerFromChar" to convert the single character to a single digit integer. So if the numbers received were "1" and "7". It would convert that to the integers 1 and 7 using that intergerFromChar function. But then you have to do some calculations on these integers ( & not the characters), to make that into the double digit number 17.
DeleteDoes that make sense - or have I confused you further?
You cannot multiply the Character "1" by 10. You first need to convert the the "1" to an integer, before you can multiply it by 10.
DeleteWhen i run the processing an error comes up saying "NullPointerException"
ReplyDeleteAny ideas on how to fix this ??
Make sure to place the image files (with the correct spelling), into the correct folder. Make sure you have ALL of the image files in that folder - you have to have the same amount of image files as that described in the code.
Delete