Exercise 4: Serial Communication

Part 1

Completing this section was completely straightforward, as both the digital and analog tutorials clearly showed how to construct the circuits necessary. Neither presented me with any issues, although I did experiment with reversing the value returned by the potentiometer in the analog tutorial by swapping the power and ground connections.

Part 2

For part 2 I simply connected three LEDs to the Arduino to pins 11-13. Each is wired in sequence with a 1k resistor on the long lead and the short lead directly into the ground rail on the breadboard.

For the Processing code, I adapted the Simple Write example. In doing so, I expanded the window and added two additional rectangles. Along with this, I created two more checks against the mouse’s position associated with these new rectangles. If the mouse overlaps any of the shapes, the value 1, 2, or 3, respectively, is written to the serial port.

For the Arduino’s functionality, pins 11-13 are recorded in order to utilize them for the output of the lights. Each iteration, the serial port is checked for data and, if there is data available it is saved. If this data is equal to the integers 1, 2, or 3 the associated light is then turned on via digitalWrite().

// Jordan Machalek
// Exercise 4 Part 2
// Arduino Code

// Light Pins
const int light1 = 13;                  
const int light2 = 12;
const int light3 = 11;

char val; // Data received from the serial port

void setup() {
  pinMode(light1, OUTPUT);
  pinMode(light2, OUTPUT);
  pinMode(light3, OUTPUT);
  Serial.begin(9600);             
}

 void loop() {
  // Check for serial data
   while (Serial.available()) { 
     val = Serial.read(); 
     }
   
   if (val == 1) { 
    digitalWrite(light1, HIGH); 
   } 
   else if (val == 2) {
    digitalWrite(light2, HIGH);
   }
   else if (val == 3) {
    digitalWrite(light3, HIGH);
   }
   else {
    // Turn off the lights
    digitalWrite(light1, LOW);
    digitalWrite(light2, LOW);
    digitalWrite(light3, LOW);
   }
   
   delay(10);
 }
/*
 * Jordan Machalek
 * Exercise 4 Part 2
 * Processing Code
 * Based on Simple Write example 
 */


import processing.serial.*;

Serial myPort;  // Create object from Serial class
int val;      // Data received from the serial port



void setup() 
{
  size(600, 200);
  String portName = Serial.list()[0]; // 1 for COM3, 0 is COM1
  myPort = new Serial(this, portName, 9600);
}

void draw() {
  background(255);
  if (mouseOverRect() == 1) {  // If mouse is over square,
    fill(204);                    // change color and
    myPort.write(1);              // send an H to indicate mouse is over square
  } 
  else if (mouseOverRect() == 2){                        
    fill(100);                    
    myPort.write(2);
  }
  else if (mouseOverRect() == 3) {
    fill(300);                   
    myPort.write(3);  
  }
  else {
    fill(0);                     
    myPort.write(0);  
  }
  
  // Draw squares
  rect(50, 50, 100, 100);         
  rect(250, 50, 100, 100);
  rect(450, 50, 100, 100);
}

int mouseOverRect() { // Test if mouse is over square
  if ((mouseX >= 50) && (mouseX <= 150) && (mouseY >= 50) && (mouseY <= 150)){
    return 1;
  }
  else if ((mouseX >= 250) && (mouseX <= 350) && (mouseY >= 50) && (mouseY <= 150)) {
    return 2;
  }
  else if ((mouseX >= 450) && (mouseX <= 550) && (mouseY >= 50) && (mouseY <= 150)) {
    return 3;
  }
  
  return 0;
  // return ((mouseX >= 50) && (mouseX <= 150) && (mouseY >= 50) && (mouseY <= 150));
}

Part 3

To set up the Arduino, I connected three photocells to read analog input. Each was connected directly to the 5V rail of the breadboard via one pin. The other pin of each cell was flanked on one side by a 10k resistor leading back to the ground rail and by a wire leading back to analog pins A0 – A2 on the Arduino.

In code, the value of each photocell is saved and then mapped from their raw value to a range of 0 – 255. First, however, the establishContact() method is used to ensure that serial data is being transmitted. Each iteration of the loop also implements a delay of 1ms to limit sensor readings.

In processing, the data from the serial port is read in and stored in an array. The values in the array, ranging from 0 – 255 are then used to manipulate the position and color of a circle and square that are drawn to a window, the background of which is also changed with these values. The random() function is used to introduce some variability to color and position. Each time that three values are recorded from the serial stream, a message is sent back to the Arduino requesting the next sequence to be sent.

/*
 * Jordan Machalek
 * Exercise 4 part 3
 * Arduino Code
 * Adapted from Processing Simple Read  and Arduino SerialCallResponse examples
 */

// Pin #'s
const int photo1 = A0;
const int photo2 = A1;
const int photo3 = A2;
int inByte = 0;         // incoming serial byte

// Sensor values
int photo1Val = 0;
int photo2Val = 0;
int photo3Val = 0;

void setup() {
  pinMode(photo1, INPUT);
  pinMode(photo2, INPUT);
  pinMode(photo3, INPUT);
  
  Serial.begin(9600);           
      
  establishContact(); 
}

void loop() {
  // if we get a valid byte, read analog ins:
  if (Serial.available() > 0) {
    // get incoming byte:
    inByte = Serial.read();

    // Read photocell values
    photo1Val = analogRead(photo1);
    photo2Val = analogRead(photo2);
    photo3Val = analogRead(photo3);
    
    // Map photocell values
    int redMap = map(photo1Val, 0, 1024, 0, 255);
    int greenMap = map(photo2Val, 0, 1024, 0, 255);
    int blueMap = map(photo3Val, 0, 1024, 0, 255);
    
    // Write to serial port
    Serial.write(redMap);
    Serial.write(greenMap);
    Serial.write(blueMap);
    
    delay(1000);
  }
}

void establishContact() {
  while (Serial.available() <= 0) {
    Serial.print('A');   // send a capital A
    delay(300);
  }
}
/*
 * Jordan Machalek
 * Exercise 4 part 3
 * Processing Code
 * Adapted from Processing Simple Read and Arduino SerialCallResponse examples
 */

import processing.serial.*;

// Serial data
Serial myPort;                     
int[] serialData = new int[3];   
int serialCount = 0;   
boolean firstContact = false;

// Sketch data
int bgColor;          
color fillColor;         
color fillColor2;
int xPos, yPos, xPos2, yPos2; // coordinates of shapes  
          
void setup() 
{
  size(200, 200);
  String portName = Serial.list()[0];
  myPort = new Serial(this, portName, 9600);
}

void draw() {
    background(serialData[0], serialData[1], serialData[2]);
    fill(fillColor);
    
    // Draw shapes
    ellipse(xPos, yPos, 20, 20);
    fill(fillColor2);
    square(xPos2, yPos2, 30);
}

void serialEvent(Serial myPort) {
  // read a byte from the serial port:
  int inByte = myPort.read();
  
  // if this is the first byte received, and it's an A, clear the serial
  // buffer and note that you've had first contact from the microcontroller.
  // Otherwise, add the incoming byte to the array:
  if (firstContact == false) {
    if (inByte == 'A') {
      // Clear data
      myPort.clear();       
      firstContact = true; 
      myPort.write('A'); 
    }
  }
  else {
    // Add the latest byte from the serial port to array:
    serialData[serialCount] = inByte;
    serialCount++;

    // When 3 values have been recorded, do something with them
    if (serialCount > 2 ) {
      // Use
      xPos = serialData[0];
      yPos = serialData[1];
      fillColor = color(serialData[0], serialData[1], serialData[2]);
      
      xPos2 = serialData[0] + (int)random(-10, 10);
      yPos2 = serialData[1] + (int)random(-10, 10);
      fillColor2 = color(serialData[0] + random(-50, 50), serialData[1] + random(-50, 50), serialData[2] + random(-50, 50));

      // print the values (for debugging purposes only):
      println(xPos + "\t" + yPos + "\t" + fillColor);

      // Send a capital A to request new sensor readings:
      myPort.write('A');
      // Reset serialCount:
      serialCount = 0;
    }
  }
}

Part 4

In this part, I connected both a potentiometer and toggle switch to the Arduino to control video. The potentiometer is connected with the center pin to analog pin A0 on the Arduino and the left and right pins to ground and 5V power. The switch is connected to digital pin 13 and ground via a 10k resistor on an end pin and to power via its center pin.

For the Arduino functions, each iteration of the loop the state of the switch and the value of the potentiometer are recorded. The potentiometer value is mapped from its native 0-1024 range to a range of 1-100. Both this value and the switch state are written to the serial stream.

In Processing, using the video library a local file is retrieved and played on loop in a window. Through serial, the value of the potentiometer and state of the switch are retrieved and stored. Each Draw() call, the switch state value will be check and either play or pause the video. The potentiometer value will also be used to adjust the playback speed of the video.

/*
 * Jordan Machalek
 * Exercise 4 part 4
 */

// Pin #'s
const int switchPin = 13;
const int potentPin = A0;
int inByte = 0;

// Sensor values
int switchState = 0;
int sensorValue = 0;

void setup() {
  pinMode(switchPin, INPUT);
  pinMode(potentPin, INPUT);
  
  Serial.begin(9600);           
      
  establishContact(); 
}

void loop() {
  // if we get a valid byte, read analog ins:
  if (Serial.available() > 0) {
    // get incoming byte:
    inByte = Serial.read();

    // Get switch state
    switchState = digitalRead(switchPin);

    // Read photocell values
    sensorValue = analogRead(potentPin);

    // Map sensor value
    int  sensorMap = map(sensorValue, 0, 1024, 1, 100);
    
    // Write to serial port
    // If the switch is on send 1, if off send 0
    if(switchState == HIGH) {
      Serial.write(1);
    }
    else {
      Serial.write(0);
    }
    // Send the mapped sensor value
    Serial.write(sensorMap);
    
    delay(10);
  }
}

void establishContact() {
  while (Serial.available() <= 0) {
    Serial.print('A');   // send a capital A
    delay(300);
  }
}
/*
 * Jordan Machalek
 * Exercise 4 part 4
 * Adapted from: 
 * https://funprogramming.org/125-Simple-video-player-in-Processing.html
 */

import processing.serial.*;
import processing.video.*;

String VIDEO_PATH = "Downloads/095.MOV";
Movie mov;

// Serial data
Serial myPort;                     
int[] serialData = new int[2];   
int serialCount = 0;   
boolean firstContact = false;

// Sketch data
int movieSpeed = 5;
boolean isPlaying = true;
          
void setup() 
{
  size(640, 360);
  
  String portName = Serial.list()[0];
  
  myPort = new Serial(this, portName, 9600);
  
  frameRate(30);
  mov = new Movie(this, VIDEO_PATH);
  mov.loop();
  mov.speed(5);
  mov.volume(0);
}

void draw() {
  if (mov.available()) {
    mov.read();
  }
  
  image(mov, 0, 0, width, height);
  
  // Pause or play the video
  if(isPlaying == true){
    mov.play();
  }
  else if(isPlaying == false) {
    mov.pause();
  }
  
  // Set the speed of the video
  mov.speed(movieSpeed);
}

void serialEvent(Serial myPort) {
  // read a byte from the serial port:
  int inByte = myPort.read();
  
  // if this is the first byte received, and it's an A, clear the serial
  // buffer and note that you've had first contact from the microcontroller.
  // Otherwise, add the incoming byte to the array:
  if (firstContact == false) {
    if (inByte == 'A') {
      // Clear data
      myPort.clear();       
      firstContact = true; 
      myPort.write('A'); 
    }
  }
  else {
    // Add the latest byte from the serial port to array:
    serialData[serialCount] = inByte;
    serialCount++;

    // When 3 values have been recorded, do something with them
    if (serialCount > 1 ) {
      
      // Pause or play the video
      if(serialData[0] == 1){
        isPlaying = true;
      }
      else if(serialData[0] == 0) {
        isPlaying = false;
      }
      
      // Set the speed of the video
      movieSpeed = serialData[1];
      
      // Print data to console
      println(serialData[0] + "\t" + serialData[1] + "\t");

      // Send a capital A to request new sensor readings:
      myPort.write('A');
      // Reset serialCount:
      serialCount = 0;
    }
  }
}

Part 5

To connect the compass to the Arduino, power is provided via the 3.3V pin rather than the 5V and ground as usual. The SCL connection was wired to the analog pin A5 and SDA connection wired to the analog pin A4.

To interface with the compass I utilzed Adafruit’s accelerometer example and combined this with my Part 3 code. This sends mapped X, Y, and Z values of the accelerometer via serial to Processing. There, it utilizes the data to manipulate the position and color of a circle and the sketch’s background.

/*
 * Jordan Machalek
 * Exercise 4 Part 5
 * Adapted from: https://github.com/adafruit/Adafruit_LSM303DLHC/tree/master/examples/accelsensor
 */
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_LSM303_U.h>

int inByte = 0;

// Assign a unique ID to the sensor
Adafruit_LSM303_Accel_Unified accel = Adafruit_LSM303_Accel_Unified(45621);

void setup()
{
#ifndef ESP8266
  while (!Serial);     // Pause until the serial console opens
#endif
  Serial.begin(9600);
  Serial.println("Accelerometer Test"); Serial.println("");

  /* Initialise the sensor */
  if(!accel.begin())
  {
    /* There was a problem detecting the ADXL345 ... check your connections */
    Serial.println("Ooops, no LSM303 detected ... Check your wiring!");
    while(1);
  }
}

void loop()
{
  /* Get a new sensor event */
  sensors_event_t event;
  accel.getEvent(&event);

  if (Serial.available() > 0) {
    // get incoming byte:
    inByte = Serial.read();
  
    // Print data for clarity
    Serial.print("X Raw: "); Serial.print(accel.raw.x); Serial.print("  ");
    Serial.print("Y Raw: "); Serial.print(accel.raw.y); Serial.print("  ");
    Serial.print("Z Raw: "); Serial.print(accel.raw.z); Serial.println("");

    // Map values
    int xValMap = map(accel.raw.x, -1024, 1024, 0, 255);
    int yValMap = map(accel.raw.y, -1024, 1024, 0, 255);
    int zValMap = map(accel.raw.x, -1024, 1024, 0, 255);

    // Send to serial
    Serial.write(xValMap);
    Serial.write(yValMap);
    Serial.write(zValMap);
    
    delay(1000);
  }

}

void establishContact() {
  while (Serial.available() <= 0) {
    Serial.print('A');   // send a capital A
    delay(300);
  }
}
/*
 * Jordan Machalek
 * Exercise 4 Part 5
 * Processing Code
 * Adapted from Processing Simple Read and Arduino SerialCallResponse examples
 */

import processing.serial.*;

// Serial data
Serial myPort;                     
int[] serialData = new int[3];   
int serialCount = 0;   
boolean firstContact = false;

// Sketch data
int bgColor;          
color fillColor;        
int xPos, yPos;
          
void setup() 
{
  size(200, 200);
  String portName = Serial.list()[0];
  myPort = new Serial(this, portName, 9600);
}

void draw() {
    background(serialData[0], serialData[1], serialData[2]);
    fill(fillColor);
    
    // Draw shapes
    ellipse(xPos, yPos, 20, 20);
}

void serialEvent(Serial myPort) {
  // read a byte from the serial port:
  int inByte = myPort.read();
  
  // if this is the first byte received, and it's an A, clear the serial
  // buffer and note that you've had first contact from the microcontroller.
  // Otherwise, add the incoming byte to the array:
  if (firstContact == false) {
    if (inByte == 'A') {
      // Clear data
      myPort.clear();       
      firstContact = true; 
      myPort.write('A'); 
    }
  }
  else {
    // Add the latest byte from the serial port to array:
    serialData[serialCount] = inByte;
    serialCount++;

    // When 3 values have been recorded, do something with them
    if (serialCount > 2 ) {
      // Use
      xPos = serialData[0];
      yPos = serialData[1];
      fillColor = color(serialData[0], serialData[1], serialData[2]);
      
      // print the values (for debugging purposes only):
      println(xPos + "\t" + yPos + "\t" + fillColor);

      // Send a capital A to request new sensor readings:
      myPort.write('A');
      // Reset serialCount:
      serialCount = 0;
    }
  }
}

Leave a comment

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Create your website at WordPress.com
Get started
%d bloggers like this: