Reading Reflection:

I’ve spent the past few nights reading a magazine called Foxfire (despite the name it’s far more innocent than it sounds). This magazine was originally published in 1977 and was compiled by a group of teenagers as part of an english class - it’s many articles compile the vernacular knowledge of Appalachia in the form of interviews and photo essays. Amongst these are sections on how to make wooden locks, wooden toys for children, or plans and instructions for the construction of wooden cabins. I bring this up because of how utterly stark the contrast is between the images in Foxfire and those presented in Igoe’s blogpost (Physical Computing’s Greatest Hits). And somewhere in that chasm is inserted Norman’s discussion on design - possibly, Igoe’s examples and Foxfire’s vernacular knowledge are opposite poles on a sliding scale mediated by how “immediate” a design object might be. I mean immediate in a rooted sense - how close the design is to a lived experience, where design responds to a physical and critical necessity.

This is not to say that one is better than the other - I won’t pretend that artistic exploration can somehow be equated to vernacular design. On the other hand, I don’t think it’s a failed comparison either - Cristopher Alexander manages to straddle the two poles in his work (i.e. A Pattern Language). What irks me about that original juxtaposition (Foxfire vs. Igoe’s examples) is that every single design object in Foxfire seems completely inevitable, whereas most design objects in Igoe’s post seem fetishistic (he even says as much, in talking about LED’s). And I think this is in part (going back to Norman) because we still do not have a vocabulary to talk about design in relation to the virtual - or rather, a vocabulary that manages to lift the fog from that strange liminal space between the “real” and code/logic/circuit. Norman’s book was first published in 1988: while his tenets of design terminology are fantastic guideposts to thinking of design as a formal endeavor, we cannot hope to begin to use them to qualify, label, or judge the quality of “interactive art”. And until we figure out a better way to do so, I sometimes am left with the feeling that we’ll forever be stuck in that strange corner of techno-fetishism that seems to define so much of our work.

Labs:

IMG_0950 (1).gif

IMG_0951.gif

Code snippet showing how new high-low values can be continuously re-mapped to “discover” the full range of the sensor:

// Base threshold values.
int analogLow, analogHigh = 400;
int currReading;
int pinA = 10;
int pinB = 9;
int sensA = A0;
int sensB = A1;

void setup() {
  Serial.begin(9600);
  pinMode(pinA, OUTPUT);
  pinMode(pinB, OUTPUT);
}

void loop() {
  // Read from 1, we assume the other sensor to be the same.
  currReading = analogRead(sensA);
  // Set new high/low records.
  analogLow = min(currReading, analogLow);
  analogHigh = max(currReading, analogHigh);
  // Write the mapped values.
  analogWrite(10, map(analogRead(sensA), analogLow, analogHigh, 0, 255));
  analogWrite(9, map(analogRead(sensB), analogLow, analogHigh, 0, 255));
}

Creative Pursuits:

Etch-a-sketch

What followed was some exploration with rotary encoders and bridging the gap with Processing via serial communication and some basic parsing. I borrowed from an open source rotary encoder library and used it to pass on data to a Processing sketch via the Serial bus - I used this data to drive a basic etch-a-sketch type game. Despite how simple it was it was, the result was quite satisfying - it was nice to brush up on the intricacies of serial comms, and also remember how much I detest C++.

IMG_0958.JPG

Processing code:

import processing.serial.*;
String[] matches;
FloatDict cursor;

Serial myPort;

void setup() {
  size(500, 500);
  background(255);
  cursor = new FloatDict();
  cursor.set("x", 500/2);
  cursor.set("y", 500/2);
  
  printArray(Serial.list());
  myPort = new Serial(this, Serial.list()[2], 9600);
}

void draw() {
  while (myPort.available() > 0) {
    String inByte = myPort.readString();
    if (inByte != null) {
      println(inByte.trim());
      // parse our input - granted this could be a lot more efficient.
      matches = match(inByte, "L:(\\\\-?[0-9]+)\\\\sR:(\\\\-?[0-9]+)");
      if (matches != null) {
        println(matches[2]);
        cursor.set("x", 250 + float(matches[1]));
        cursor.set("y", 250 + float(matches[2]));
      }
     
    }
  }
  fill(0);
  circle(cursor.get("x"), cursor.get("y"), 20);
}

Arduino code:

// -----
// SimplePollRotator.ino - Example for the RotaryEncoder library.
// This class is implemented for use with the Arduino environment.
//
// Copyright (c) by Matthias Hertel, <http://www.mathertel.de>
// This work is licensed under a BSD 3-Clause License. See <http://www.mathertel.de/License.aspx>
// More information on: <http://www.mathertel.de/Arduino>
// -----
// 18.01.2014 created by Matthias Hertel
// 04.02.2021 conditions and settings added for ESP8266
// 15.09.2024 modified for two rotary encoders and simplified protocol by Nikolai Kozak
// -----

#include <Arduino.h>
#include <RotaryEncoder.h>

#define PIN_IN1 A2
#define PIN_IN2 A3
#define PIN_IN3 A4
#define PIN_IN4 A5

// Setup a RotaryEncoder with 4 steps per latch for the 2 signal input pins:
// RotaryEncoder encoderLeft(PIN_IN1, PIN_IN2, RotaryEncoder::LatchMode::FOUR3);

// Setup a RotaryEncoder with 2 steps per latch for the 2 signal input pins:
RotaryEncoder encoderLeft(PIN_IN1, PIN_IN2, RotaryEncoder::LatchMode::TWO03);
RotaryEncoder encoderRight(PIN_IN3, PIN_IN4, RotaryEncoder::LatchMode::TWO03);

void setup()
{
  Serial.begin(115200);
  while (! Serial); // smart little trickery here
} // setup()

void loop()
{
  static int posLeft = 0;
  static int posRight = 0;
  encoderLeft.tick();
  encoderRight.tick();

  int newPosLeft = encoderLeft.getPosition();
  int newPosRight = encoderRight.getPosition();
  
  // Simplified output so we can more easily parse it in P.
  if (posLeft != newPosLeft || posRight != newPosRight) {
    Serial.print("L:");
    Serial.print(newPosLeft);
    Serial.print(" R:");
    Serial.println(newPosRight);
    posLeft = newPosLeft;
    posRight = newPosRight;
  }
  
}

Screenshot 2024-09-15 at 16.14.18.png

Screenshot 2024-09-15 at 16.15.37.png

LED Slider

I wanted to work on visualizing the output of one of our sensors - I liked the idea of making it immediate and interactive, in a more intuitive way than a stream of numbers. I worked out a way to map a percentage onto a set of LED’s so that these would act as a sort of “slider” that I could easily call to reflect the state of a sensor. I wanted to turn this into a game, where you “the human” would have to be able to hold a given sensor value accurately - from iteration to iteration, the sensor range would be remapped, and thus the difficulty of the task would change.