Kinetic Energy Project

For our Kinetic Energy project, we decided to create a chore wheel for the ITP kitchen!

Fabrication

We purchased a wall clock from K-mart, and removed the hands and some of the decorative elements. We fitted a 100 RPM geared DC motor through its center, attaching a handle of wood to the motor using a mounting hub. We added a white acrylic to the face of the “clock,” replacing the numbers of the clock with chores!

This is what it looked like before we added in the lettering:


Electronics

To build our circuit, we started with the rectification circuit from Jeff’s video. Initially, we considered powering a series of LEDs that blinked as a few capacitors in parallel charged and discharged. However, we wanted more control over the behavior of the LEDs (but wanted to avoid overcomplicating our analog circuit). We decided to experiment with powering an ATTiny85 (I have had a bit of previous experience playing around with those).

We added a voltage regulator to the rectification circuit, and dropped down to one 470 mF capacitor. We ran a few experiments with running simple programs (such as Blink) on the ATTiny, and then finally, strandtest from the Neopixel sample code.

Once we had the circuit working, we soldered it onto some perfboard.


Code

Timothy put together this bit of code for animating our Neopixel strip:

#include <Adafruit_NeoPixel.h>

#define NUM_LEDS 51
#define STRIP_PIN 3 // change that

unsigned int timeStamp = 0; // milliseconds
int timePeriod = 200; // milliseconds
byte LEDPosition = 0;
byte nextNum = 0;
byte chance = 2; // 2%
bool active = true;

Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUM_LEDS, STRIP_PIN, NEO_GRB + NEO_KHZ800);

void setup() {
  pixels.begin();
  delay(10);

  randomSeed(analogRead(2));
  delay(2); 
  timePeriod = random(30,150);

}

void loop() {
  if (millis() - timeStamp >= timePeriod && active){
    pixels.clear();
    delay(10);
    if (LEDPosition >= 0 && LEDPosition <= NUM_LEDS-5) {
      pixels.setPixelColor(LEDPosition, pixels.Color(255,255,255));
      pixels.setPixelColor(LEDPosition+1, pixels.Color(255,255,255)); 
      pixels.setPixelColor(LEDPosition+2, pixels.Color(255,255,255)); 
      pixels.setPixelColor(LEDPosition+3, pixels.Color(255,255,255));
      pixels.setPixelColor(LEDPosition+4, pixels.Color(255,255,255));
      pixels.setPixelColor(LEDPosition+5, pixels.Color(255,255,255));
    } else {
      pixels.setPixelColor(LEDPosition, pixels.Color(255,255,255));
      for(int i=1; i<=5; i++){
        nextNum = LEDPosition+i;
        
        if (nextNum > NUM_LEDS){
          nextNum-=NUM_LEDS+1;
        }

        pixels.setPixelColor(nextNum, pixels.Color(255,255,255));
      }
    }
    pixels.show();
    LEDPosition++;
    if (LEDPosition == NUM_LEDS+1) {
      LEDPosition = 0;
    }
    if (random(0,100) <= chance){
      active = false;
    }
    timeStamp = millis();
  }
}

We ran into an interesting problem with our random function on the ATTiny85 – it simply wasn’t as random as one would hope (the chore wheel always stopped at the same point). We looked into how random functions on the ATTiny85, and realized that was not truly making new random numbers each time the function was called. To rectify this issue, we added randomSeed(analogRead(2)); to our setup() to read in a few “random” values on our analog pin. This improved the behavior of the random function.

Here’s how it all came together:

#energy 


Sending Data over MQTT

Our assignment this week was to build upon the “device to database” contraption we started in class (well, no db just yet). As we had already implement something including a temperature and humidity sensor, I decided to add light to the mix. I kept it pretty simple: I added a photoresister and a 470 ohm resistor going to ground. I ran a jumper wire just before the 470 going into A3 of my MKR1000.

The “IRL” view of this setup can be viewed here:

Here's what the breadboard looks like:

(You’ll notice this does not include the LED, which I end up not utilizing in my final sketch for this assignment).

I had to very minimally modify the code in order to accomodate the additional sensor. Initially, I only made modifications to HardwareTest.ino (the sketched use in class). The results of that code here:

The code is here:

// IoT Workshop
// Send temperature and humidity data to MQTT
//
// Uses WiFi101 https://www.arduino.cc/en/Reference/WiFi101 (MKR1000)
// Uses WiFiNINA https://www.arduino.cc/en/Reference/WiFiNINA (MKR WiFi 1010)
// Arduino MQTT Client Library https://github.com/arduino-libraries/ArduinoMqttClient
// Adafruit DHT Sensor Library https://github.com/adafruit/DHT-sensor-library
// Adafruit Unified Sensor Library https://github.com/adafruit/Adafruit_Sensor
//

#include <SPI.h>
#ifdef ARDUINO_SAMD_MKR1000
#include <WiFi101.h>
#define WL_NO_MODULE WL_NO_SHIELD 
#else
#include <WiFiNINA.h>
#endif
#include <ArduinoMqttClient.h>

#include "config.h"

WiFiSSLClient net;
MqttClient mqtt(net);

// Temperature and Humidity Sensor
#include <DHT.h>
#define DHTTYPE DHT22
#define DHTPIN  7
#define photoPIN A3
DHT dht(DHTPIN, DHTTYPE);
int value; 
int maxVal = 0; 
int minVal = 1023;

String temperatureTopic = "itp/" + DEVICE_ID + "/temperature";
String humidityTopic = "itp/" + DEVICE_ID + "/humidity";
String lightTopic = "itp/" + DEVICE_ID + "/light";

// Publish every 10 seconds for the workshop. Real world apps need this data every 5 or 10 minutes.
unsigned long publishInterval = 10 * 500;
unsigned long lastMillis = 0;

void setup() {
  Serial.begin(9600);

  // Uncomment next line to wait for a serial connection
  // while (!Serial) { }
 
  // initialize temperature sensor
  dht.begin();  
  pinMode(photoPIN, INPUT);  
 
  Serial.println("Connecting WiFi");
  connectWiFi();
}

void loop() {
  if (WiFi.status() != WL_CONNECTED) {
    connectWiFi();
  }

  if (!mqtt.connected()) {
    connectMQTT();
  }
  
  // poll for new MQTT messages and send keep alives
  mqtt.poll();

  if (millis() - lastMillis > publishInterval) {
    lastMillis = millis();

    float temperature = dht.readTemperature(true);
    float humidity = dht.readHumidity();
    value = analogRead(photoPIN); 

    if (value > maxVal) maxVal = value;
    if (value < minVal) minVal = value;
    int mappedValue = map(value, minVal, maxVal, 0, 100);

    Serial.print(temperature);
    Serial.print("°F ");
    Serial.print("% RH ");
    Serial.print(mappedValue);
    Serial.println(" light level");
    
    mqtt.beginMessage(temperatureTopic);
    mqtt.print(temperature); 
    mqtt.endMessage();

    mqtt.beginMessage(humidityTopic);
    mqtt.print(humidity); 
    mqtt.endMessage();

    mqtt.beginMessage(lightTopic);
    mqtt.print(mappedValue); 
    mqtt.endMessage();
  }  
}

void connectWiFi() {
  // Check for the WiFi module
  if (WiFi.status() == WL_NO_MODULE) {
    Serial.println("Communication with WiFi module failed!");
    // don't continue
    while (true);
  }

  Serial.print("WiFi firmware version ");
  Serial.println(WiFi.firmwareVersion());
  
  Serial.print("Attempting to connect to SSID: ");
  Serial.print(WIFI_SSID);
  Serial.print(" ");

  while (WiFi.begin(WIFI_SSID, WIFI_PASSWORD) != WL_CONNECTED) {
    // failed, retry
    Serial.print(".");
    delay(3000);
  }

  Serial.println("Connected to WiFi");
  printWiFiStatus();

}

void connectMQTT() {
  Serial.print("Connecting MQTT...");
  mqtt.setId(DEVICE_ID);
  mqtt.setUsernamePassword(MQTT_USER, MQTT_PASSWORD);

  while (!mqtt.connect(MQTT_BROKER, MQTT_PORT)) {
    Serial.print(".");
    delay(5000);
  }

  Serial.println("connected.");
}

void printWiFiStatus() {
  // print your WiFi IP address:
  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);
}

It’s a modification of the TemperatureHumidity.ino code we used in class. I added a few lines to set the pinMode on A3, analogRead that pin, and publish to a new MQTT topic. You’ll also notice that I’m mapping the values I am receiving from analogRead() to values between 0 and 100. This seemed like a more intuitive way to report out light levels (rather than the range of actual values sent by the photoresistor).

You can also see how this data looks from the MQTT broker side (here’s I’m using the subscribe example shared in class):

Just the light!

#device_to_db 


Energy: Initial Experimentation

For the first week’s assignment in Energy, we had the task of flashing an LED by using an motor or magnet and wire. We tried quite a few things, the most successful being the use of a stepper motor to generate electricty, seen below:

I was really curious to see if a scrappier solution was possible using a magnet and wire. I based the construction of my setup on this video:

I definitely had some issues fabricating this structure, but ended up with something that vaguely resembled the structure in the video. I didn’t have the appropriate lightbulb to recreate the setup in the video, so I decided to just connect my multimeter to see what kind of voltage it yielded. I also “cheated” a bit by using a screw driver to spin my metal rod, rather than my own hands…

As you see, I was able to produce barely 0.01 V this way.

I wanted to compare this to what I could accomplish on a simple DC motor, seen below:

The DC motor yield 0.3 V when I just used my hands to spin its shaft.

#energy 


Artist in the Archive: In a Haystack

For this assignment, we had the broad task of locating something of interest in the vast collections of the Library of Congress. Initially, I poked through the featured digital collections, but soon came to fear the prospect that everyone would take this tack. After poking through some old insurance maps and I decided to just use the search feature at loc.gov. I’ve been really interested in the McCarthy Era lately, so I decided to search for “Senator McCarthy.”

This search brought me to an exhibition at the Library of Congress called “Pointing Their Pens: Herblock and Fellow Cartoonists Confront the Issues”. One of the artists featured in the exhibit was Herbert Block (or Herblock). Block had worked as an editorial cartoonist for nine decades and won four Pultizer Prizes. I noticed this comic and decided to look into its provenance:

https://www.loc.gov/exhibits/pointing-their-pens-editorial-cartoons/images/03196u_enlarge.jpg

The comic first appeared in the Washington Post in January 2, 1953. It appears with the following description in its MARC record: “Editorial cartoon drawing shows President Eisenhower as the engineer of a locomotive labeled “Ike” and flying a banner that states “Look Ahead, Neighbor”, passing a marker labeled “1953” as he races into the future; Eisenhower looks worried as another railroad car labeled “Proposed Congressional Investigations into the Past” carrying legislators dressed like detectives, rumbles into the past, intent on rooting out communists.” Its materials are described as follows: “India ink, graphite, and opaque white over graphite underdrawing.”

The piece belongs in the Herbert L. Block (Herblock) Collection, which was donated to the Library in 2002 by the Herb Block Foundation. The rights and restrictions for the cartoons in the Herblock collection can be found here. (Hopefully, the cartoons appearance on this site counts as “fair use” rather than publication…).

#artist_archive 


Animation: Experiments in Unreal

It was fun diving into Unreal for the first time. It’s clearly a really powerful tool. It reminds me a bit of the Sims, which is great. I took a Sims-like approach to what I made for homework. I wanted to construct a set for my Mrs. Davis character. Mrs. Davis, if you’ll remember from my last post, is my 4th grade teacher. She was really lovely, and when I wondered what Mrs. Davis would be up to today, I thought she might be working at a startup like the other cool kids.

Initially, I wanted to animate an office party scene with many other characters, but given my troubles with Fuse crashing constantly, and I decided that the party would only feature Mrs. Davis animations.

The party became a nightmare, featuring Mrs. Davis’s birthday with many Mrs. Davis’s having a variety of reactions to the momentous occassion. I struggled a bit with getting the camera to behave as I wanted but there is the result regardless:


I realized I showed the wrong tiny clip in class, but alas.

#animation