W3

This week, we use X-Bees and adaptors to let two Lilypads talk to each other. Compared to what I have done before with Arduino Uno, I think X-Bees definitely are more coding friendly, and the serial communication is very smooth during the whole process. So after setting up all the variables in the XCTU (one tip here is never to use 1234 as the pan ID since it’s used too often and you may receive someone else’s input), we begin the connect all the components together and flow of current is relatively easy to understand.

Exercise 1: Control the brightness of a LED

We also use the example code to smooth out the sharp change in the value of the customized potentiometer. 

Exercise 2: Processing


 

I would say the most crucial step in the Processing code is to find the right port so that the serial communication can process successfully (I really don’t understand how comes I have so many ports already occupied by Bluetooth devices).

import processing.serial.*;

int NUM_OF_VALUES_FROM_XBEE = 1;   /** YOU MUST CHANGE THIS ACCORDING TO YOUR PROJECT **/
int sensorValues[];      /** this array stores values from the Lilypad1 **/

String myString = null;
Serial myPort;
void setup() {
  setupSerial();
}
void setupSerial() {
  printArray(Serial.list());
  myPort = new Serial(this, Serial.list()[11], 9600);
  // WARNING!
  // You will definitely get an error here.
  // Change the PORT_INDEX to 0 and try running it again.
  // And then, check the list of the ports,
  // find the port "/dev/cu.usbmodem----" or "/dev/tty.usbmodem----" 
  // and replace PORT_INDEX above with the index number of the port.

  myPort.clear();
  // Throw out the first reading,
  // in case we started reading in the middle of a string from the sender.
  myString = myPort.readStringUntil( 10 );  // 10 = '\n'  Linefeed in ASCII
  myString = null;

  sensorValues = new int[NUM_OF_VALUES_FROM_XBEE];
}
void draw() {
  getSerialData();
  printArray(sensorValues);

  float size = map(sensorValues[0], 0, 1023, 0, width);
  circle(width/2, height/2, size);
}
void getSerialData() {
  while (myPort.available() > 0) {
    myString = myPort.readStringUntil( 10 ); // 10 = '\n'  Linefeed in ASCII
    if (myString != null) {
      String[] serialInArray = split(trim(myString), ",");
      if (serialInArray.length == NUM_OF_VALUES_FROM_XBEE) {
        for (int i=0; i<serialInArray.length; i++) {
          sensorValues[i] = int(serialInArray[i]);
        }
      }
    }
  }
}

Exercise 3: FastLED

In this exercise, we use the customized potentiometer to control the LED strip. While I only can understand part of the Fast LED library and the code is merely controlling one LED blinking, the idea and the logic behind it are the same.

#include <SoftwareSerial.h>
#include <FastLED.h>
SoftwareSerial mySerial(10, 11); // RX, TX

const int numReadings = 10;

int readings[numReadings];      // the readings from the analog input
int readIndex = 0;              // the index of the current reading
int total = 0;                  // the running total
int average = 0;

#define NUM_OF_VALUES_FROM_XBEE 1    /** YOU MUST CHANGE THIS ACCORDING TO YOUR PROJECT **/
#define NUM_LEDS 50
#define DATA_PIN 3
/** DO NOT REMOVE THESE **/
int tempValue = 0;
int valueIndex = 0;
int xbee_values[NUM_OF_VALUES_FROM_XBEE];

CRGB leds[NUM_LEDS];

void setup() {
  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  pinMode(9, OUTPUT);
  mySerial.begin(9600);
  FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);  // GRB ordering is assumed
  for (int thisReading = 0; thisReading < numReadings; thisReading++) {
    readings[thisReading] = 0;
  }
}

void loop() {
  getSerialData();
  total = total - readings[readIndex];
  // read from the sensor:
  readings[readIndex] = xbee_values[0];
  // add the reading to the total:
  total = total + readings[readIndex];
  // advance to the next position in the array:
  readIndex = readIndex + 1;

  // if we're at the end of the array...
  if (readIndex >= numReadings) {
    // ...wrap around to the beginning:
    readIndex = 0;
  }

  // calculate the average:
  average = total / numReadings;
  average = constrain(average, 0, 300);
  average = map(average, 0, 300, 0, 255);
  if (average > 210) {
//    for (int i; i < 50; i++) {
      leds[ 0] = CRGB::Red;

      FastLED.show();
      //delay(500);
//    }
  } else {
//    for (int i; i < 50; i++) {
      leds[0] = CRGB::Black;

      FastLED.show();
      //delay(500);
//    }
  }

}

//receive serial data from Processing
void getSerialData() {
  while (mySerial.available()) {
    char c = mySerial.read();
    //switch - case checks the value of the variable in the switch function
    //in this case, the char c, then runs one of the cases that fit the value of the variable
    //for more information, visit the reference page: https://www.arduino.cc/en/Reference/SwitchCase
    switch (c) {
      //if the char c from Processing is a number between 0 and 9
      case '0'...'9':
        //save the value of char c to tempValue
        //but simultaneously rearrange the existing values saved in tempValue
        //for the digits received through char c to remain coherent
        //if this does not make sense and would like to know more, send an email to me!
        tempValue = tempValue * 10 + c - '0';
        break;
      //if the char c from Processing is a comma
      //indicating that the following values of char c is for the next element in the values array
      case ',':
        xbee_values[valueIndex] = tempValue;
        //reset tempValue value
        tempValue = 0;
        //increment valuesIndex by 1
        valueIndex++;
        break;
      //if the char c from Processing is character 'n'
      //which signals that it is the end of data
      case '\n':
        //save the tempValue
        //this will b the last element in the values array
        xbee_values[valueIndex] = tempValue;
        Serial.println(tempValue);
        //reset tempValue and valueIndex values
        //to clear out the values array for the next round of readings from Processing
        tempValue = 0;
        valueIndex = 0;
        break;
    }
  }
}

I think today’s exercise can be implemented well in interactive clothes design as it enables you to place the input and the output separately. Imagine the scene where you are generating some inputs near the head, it’s more convenient for the wiring if you are going to exhibit the output somewhere near your feet.

Leave a Reply

Your email address will not be published. Required fields are marked *