Transcript Document

ProtoSnaps and Processing

Serial Interfacing and Sensor Calibration Materials by Lindsay Craig and Ben Leduc-Mills

ProtoSnap and Processing Class Overview

• What is Processing? Installation and Intro • Serial Comm from Arduino to Processing • Calibration of Sensors • Sensor Variables • Serial Comm from Processing to Arduino • Controlling and Using Physical Aspects of ProtoSnap Interface • Controlling Serial Comm and Handling Specific Events

Processing?

• Processing is a free, open source, cross platform programming language and environment for people who want to create images, animations, and interactions.

• Created in 2001 by Casey Reas and Ben Fry at the MIT Media Lab. • Downloads, updates, reference, forums, etc. at: http://processing.org

Installation

For Linux: Download the .tar.gz file to your home directory, then open a terminal window and type: Tar xvfz processing-xxxx.tgz

(replace xxxx with the rest of the file ’s name, which is the version number) This will create a folder named processing-1.5 or something similar. Then change to that directory: cd processing-xxxx and run processing: ./processing For Mac: Double-click the .dmg file and drag the Processing icon from inside this file to your applications folder, or any other location on your computer. Double click the Processing icon to start Processing.

For Windows: Double-click the .zip file and drag the folder inside labeled Processing to a location on your hard drive. Double click the Processing icon to start Processing. If you are stuck go to

http://wiki.processing.org/index.php/

Troubleshooting for help.

Anatomy of a sketch

A sketch is a file or project you create in Processing. When you first open up a new sketch it will be completely blank.

Setup()

This function runs once, at the very beginning of your sketch. You will use setup to set up certain aspects of your sketch, makes sense right? This is a good place to put your sensor calibration code. (More on sensor calibration later.) Most importantly for this class you will begin Serial communication in the setup function. The setup function without anything in it looks like this:

Draw()

This function is where everything happens in your sketch. The draw loop is the portion of code that keeps repeating while the Processing sketch is open. Any animation, interaction or changes to the images or variables in your sketch will need to be programmed inside of this loop. The draw loop looks like this:

How to Make Basic Graphics

Basics here

Reference

One very convenient way to access Processing ’s Help Reference is to highlight a function or a word used in your code, right click and select Find in Reference (which brings you to the processing.org reference page):

Hooking into Processing

We can send values from the ProtoSnap to Processing through an Arduino, and use these values to control things in Processing First step: Open a new Arduino sketch Like Processing, we have a setup() function In that function, we need to open Serial communication:

Serial.begin(

9600

);

Hooking into Processing

We now have to set up all pins to the right pinMode, in our setup function as well as pulling any internal pull up resistors HIGH.

We ’ll get to the establishContact() function in a bit, but don ’t forget to put it in now.

Hooking into Processing

In our loop() function, we need to read from all the sensors and send the values out the serial port by calling Serial.print

We used a delimiter to separate the sensor values so that the sensor values will be easier to distinguish when we get them into Processing.

Hooking into Processing

Here are the rest of the loop() statements. Don ’t forget the

ln

in the last Serial.println(dig italRead (7)); statement.

There is more than this in the code on your ProtoSnap, we ’ll get into that later. For now these are the basics you need to send Serial from Arduino to Processing.

Receiving Data in Processing

Now that we ’re sending data from the ProtoSnap, we need a way to receive it in Processing. Luckily, there ’s a library for that.

First, import the serial library.

We we ’ll also need a Serial object to define which serial port we ’ll be using, as well as an integer array for our sensor data. We also have a boolean variable to keep track of whether ’ve heard from Arduino or not.

In your setup function, you need to initialize your Serial object, passing it the parent object (don the baud rate. ’t worry about this) which port you want to use, and Make sure you pick the same baud rate that you defined in the Arduino sketch.

The bufferUntil function just stores our incoming data in a buffer until we ’re ready to do something with it.

import processing.serial.*; Serial usbPort ; int [ ] sensors = null ; boolean firstContact = false; void setup() { usbPort = new Serial ( this, Serial.list( ) [

0

] ,

9600

); usbPort.bufferUntil (‘

\n

’); }

Receiving Data in Processing

Our next step is to define a SerialEvent function – this function automatically gets called every time the character in our bufferUntil() statement is read from the serial port. We then read a chunk of data into a String, trim whitespace, and split it using our delimiter character (told you it would be useful!) into our sensors[ ] integer array. This puts each sensor value into its own addressable place in the array.

There is a println that should be printing out the sensors values it sees – try running the sketch to make sure you ’re getting values.

Receiving Data in Processing

There ’s a lot going on here, so don’t worry if it doesn’t make sense at first.

Basically, we check for the Serial Communication from Arduino. Once it reads a carriage return it checks to make sure the data string is not empty.

If it ’s got something, we split the string up by our delimiter character into an array. This lets us put each sensor value into its own variable. If you don ’t put the array values into their own variables you will get a null pointer exception when you try to use them in your code.

Waiting for Serial Communication Establishment

One of the first things you will have to do is create a conditional that keeps your game from starting while Processing initiates Serial Communication.

To do this use the firstContact variable as a condition for changing the screen state. Only when you have made contact with the Arduino will your game move to the next section of code.

Using Received Data in the Processing Sketch: The Button

Next let ’s keep Processing querying another conditional that waits for the user to press the button on the ProtoSnap.

To do this we will need to check a variable (gameOn boolean variable) that tells us whether we have started playing the game yet.

While that variable is false (or an integer that indicates we have not started playing the game) Processing will be stuck in a while loop that looks for a button press.

When the button is pressed Processing takes a sensor calibration reading and changes the gameOn variable to true. This allows us to begin playing the game.

Using Received Data in the Processing Sketch: The Photoresistor

In the first iteration of my game I simply mapped the light sensor value to the height of my screen. But my character never got to the top of the screen and it made my character jump all over the place due to the speed at which the light sensor values change. Before we fix this let ’s look at how we use the light sensor to control the Y position of the character. Basically the closer our hand is to the light sensor the lower the value is. This means that we mapped the lowest possible value (0) to the bottom of the screen and the highest possible value (1023) to the top of the screen. But this assumes that we have enough light to actually get that value of 1023!

Using Received Data in the Processing Sketch: The Photoresistor

So first I changed the map values so that the character was more in sync with the light values of the room in which I was programming. The room was a little dim so I used an upper light value of 150.

So I wrote this: Instead of this:

Using Received Data in the Processing Sketch: The Photoresistor

Or to fix the issue of sensor calibration we can get a value from the light sensor at the beginning of the game that we compare to the current light sensor variable. This way we can compensate for a brighter or darker environment.

Remember this in the menu function? upLightVal is our calibration variable.

And then we can use upLightVal in our mapping code in the draw loop.

But it still jumps around a lot, huh?

Using Received Data in the Processing Sketch: The Photoresistor

We can use the light sensor to move the character instead of using it to decide the position of the character. This is a subtle but important difference.

This code says two things: 1. If the light sensor is between zero and fifteen (and the character is not at the bottom of the screen) move the character down by five pixels.

2. If the light sensor is higher than five below the initial sensor calibration value (and the character is not at the top of the screen) move the character up by five pixels.

Using Received Data in the Processing Sketch: The Photoresistor

This works pretty well, but sometimes we get a bad initial calibration value and then the gamer is destined to hang out either at the top or the bottom of the screen.

Since we only have two inputs to work with we need to figure out a way to use the other input (button) to trigger taking a new calibration reading. In order to allow normal usage of the button during game play and sensor recalibration we will look for three rapid pushes of the button, something that would rarely happen during normal play.

Using Received Data in the Processing Sketch: Programming the Game

From this point out it ’s a question of game design, programming and using the variables you are receiving from Arduino in the proper manner. With more inputs this gets more exciting, but two simple inputs (one Analog and one Digital) is a great way to learn this stuff.

Any questions about the game code?

Next up we will learn how to send communication the other way, from Processing to the Arduino.

Sending Data from Processing to Arduino: The Processing Code

Good news! Since you have already imported the Processing Serial library sending Serial Communication from Processing to the Arduino is pretty simple. There are two pieces you need, very similar to the Arduino to Processing communication, but in reverse.

To send a Serial message from Processing all you have to do is find the place in your Processing sketch where you want to send a message and type the following line: Serial.write ( variable ) ; Where variable is the value you want to send to your Arduino. The next 4 slides show where the game uses the Serial.write(); function.

Sending Data from Processing to Arduino: Low Health

This portion of the code indicates that the character is low on life. The character ‘D’ is sent to the Arduino each time draw executes if the character ’s life is below twenty five.

Sending Data from Processing to Arduino: Hit Test

This is the hit test code. There is a boolean variable in it so it will only send Serial Communication or decrement the health meter when the character is first hit with an obstacle and not the entire time the character and the obstacle are touching.

Sending Data from Processing to Arduino: Shield On

This portion of the code indicates that the user is pressing the ProtoSnap button and the shield has been activated. The variable shieldSwitch is used to limit the amount of Serial Data sent to the Arduino so there is only a signal when the shield is first activated.

Sending Data from Processing to Arduino: Shield Out

This portion of the code indicates that the user is pressing the ProtoSnap button and has tried to activate the shield but there is no shield left to use. The character ‘N’ is sent every time, there is no limiting variable .

Receiving Data from Arduino to Processing: The Arduino Code Declaring a Buffer Variable and Assigning it a Value

Receiving information is usually the most difficult aspect of Serial Communication.

First we need to declare a Serial buffer variable to hold the Serial Communication, do this before your setup or loop functions. For my game I am only sending one char at a time so I declare a char variable and fill it with a zero like this.

char Signal = ‘0’;

Receiving Data from Arduino to Processing: The Arduino Code Declaring a Buffer Variable and Assigning it a Value

Then I use the following lines inside the loop function to fill that variable with the char that Arduino reads over the Serial line.

} if (Serial.available () > 0) { signal = Serial.read (); If you want to send more than one value at a time you will need to create a char array instead of a signal char variable and use a for loop to check each value in the array. You will also need to make sure that Processing sends a full array each time it sends Serial Communication or have Arduino clear the array each loop cycle so you don ’t wind up with outdated data in your Serial buffer. In this case you will need to change the if loop to a while loop because otherwise Arduino won ’t catch the entirety of the communication.

Using the Serial Variable: The Arduino Code

Now that we have data in our signal variable we can use it to control aspects of the ProtoSnap. You can do this in a bunch of different ways. We will cover two different ways to do this. One of them is a switch case and the other is an if statement.

Using the Serial Variable: The Arduino Code Switch Case

Remember to put single quotes around each variable as you create each case statement.

Using the Serial Variable: The Arduino Code If Statement

One cool thing about using if statements is that you can check if to see if the signal variable is NOT equal to a certain value.

Limiting Communication

An important thing to note is that often you will only want to send Serial Communication at the beginning or end of an event. Such as with the hit test. You may want to have something happen on the Arduino when your character is first hit with a bad guy, but the hit test will continue to trigger Serial Communication after the first contact. You can limit this on either side of the communication. We already saw how you would limit that in Processing, here is how you might limit that on the Arduino side.

Declare a boolean variable And assign the variable

Handling Different Types of Input from the Same Sensor

Put 3 presses of button here, combination for hue in menu select

Other Ways to Handle Sensor Data

Weighted variables here Running average

Other Ways to Handle Sensor Data

Various ways to weight variables here as well Running average with recent weighted

Using Physical Aspects of the ProtoSnap Interface to Affect the Sensors

The photoresistor is right next to the RGB LED. It is possible to use the LED to affect the photoresistor sensor depending on what is happening in the game. You may have noticed that when you use the shield the RGB LED lights up causing the character to move up a little. Useful if you want the character to move a little erratically when it has a low health.

Make sure the red LED doesn ’t turn off if character has low health Instead of just turning the LED on send it a random value, remember to put this code outside of your Serial.available(); if statement because we want the value to change each loop, not each time Arduino receives data.

Sensors

Dave pointed out that back in the day people were able to use a single button to send morse code. There are many different ways to stretch the interface capabilities of your sensors. Think about creating handlers for different distinct sensor values and combinations. What kind of special moves or easter eggs will the user discover if they mess around with the sensors long enough?

Questions?

www.sparkfun.com

6175 Longbow Drive, Suite 200 Boulder, Colorado 80301