GMU:Speculative Atmospheres II/Nicolas Krewer: Difference between revisions

From Medien Wiki
No edit summary
Line 29: Line 29:
==Next steps==
==Next steps==
In the next steps, the 3D parts will be printed, assembled and tested. After that, the power sources will be changed to RC batteries and the receipt printer will be implemented. The incremental rotary encoder will be replaced by an absolute rotary encoder to be able to read the exact position instead of counting steps. When all this is working the box and glass cube is built and air quality sensors can be added to the setting.
In the next steps, the 3D parts will be printed, assembled and tested. After that, the power sources will be changed to RC batteries and the receipt printer will be implemented. The incremental rotary encoder will be replaced by an absolute rotary encoder to be able to read the exact position instead of counting steps. When all this is working the box and glass cube is built and air quality sensors can be added to the setting.
<gallery>
File:3D Parts.png
File:FAN ASSEMBLY1.png
File:FAN ASSEMBLY2.png
File:FAN ASSEMBLY3.png
</gallery>


==Prototypes==
==Prototypes==

Revision as of 15:03, 1 February 2022

Concept

Inspired by the yearly happening Sisyphean task of sweeping leaves and get them blown away again by the wind. In this installation wind is captured outdoors and will be transmitted and reproduced in a hermetic like glass cube right underneath. Four fans are blowing receipts through a space in the direction and the speed from the wind outside. The fans are positioned in the corners to cover the whole room, instead the corners would be left out and paper would get stuck. The receipts are printed with information about the polluted air, which on one hand represent the leaves, but should also address the issue of a senseless environmental pollution.

Technical

To capture the wind speed and and the direction, a DIY anemometer is built. For both, photo interrupters are used. To measure the wind speed, a slotted disk is used to measure the amount of steps (on/off) in a certain time and then calculated to rpm, which will be send to control the speed of the fans. For capturing the direction, a rotary encoder is built with two photo interrupters and also a disk, that has eight on and eight off steps (for eight wind directions).

The use of an Arduino Mega is necessary to provide enough digital inputs that support interrupts, but also enough outputs for the motor controller, the printer and the other sensors. For the fans, brushless motors are used, that are also very common in drones, e-bikes, etc. They are controlled with ESC motor drivers and powered by RC batteries, so the installation can stand independently from a power socket.

For printing the receipts a standard TTL receipt printer is used together with eco friendly receipt paper. (To cut the paper a belt driven slider is built with a stepper motor and a blade attached to a module on the belt.)

Aesthetics

It is all happening in a hermetic like glass cube that is sitting on a plinth. The parts are 3D printed to look neat and integrate into the installation, but still the DIY aesthetics should come out. In the cube a layer of moss is placed which on one hand is representing nature, but is also a great natural air filter. In the center the receipt printer is positioned and after printing data about the air quality the paper is cut by a blade. The DIY sensors can be seen inside a transparent box that is sitting on top of the cube, so people can see what exactly is happening and can relate to the things happening inside the box.

Render1.png


Issues during the process

During the making there were several issues, first of all, there were problems in the code to run the rotary encoder that got fixed very quickly. Another issue to run the encoders were interrupt pins on the Arduino, which was fixed by using an Arduino Mega that has several interrupt channels. Later it turned out that the computer fans, that were bought for the prototype wouldn’t work. They turned on at a too high speed and didn’t go much higher, so they couldn’t reflect the speed from the wind and were barely able to blow any paper snippets. To solve that brushless DC motors together with ESC drivers are chosen and brought new issues. First, only one arrived and second, the power source for testing them doesn’t have a constant current which is responsible for only being able to use a higher rpm. One last big problem was that no one cooperated to 3D print the needed parts to be able to even use some functions.

Next steps

In the next steps, the 3D parts will be printed, assembled and tested. After that, the power sources will be changed to RC batteries and the receipt printer will be implemented. The incremental rotary encoder will be replaced by an absolute rotary encoder to be able to read the exact position instead of counting steps. When all this is working the box and glass cube is built and air quality sensors can be added to the setting.

Prototypes

Old Prototype without ball bearings and cardboard only


Newer Prototype made from a more solid material, with ball bearings and works/looks more like the final result

Prototype2-1.jpg Prototype2-2.jpg

Code to this point (can also be found on GitHub)

https://github.com/nk246/anemometer/tree/Anenometer


#include <Wire.h>
#include <Servo.h>
/*
#include "Adafruit_Thermal.h"
#include "SoftwareSerial.h"
*/

//Wind Speed
float rpm = 0;

int pid;
unsigned long millisBefore;
volatile int holes;


//Wind Direction
int sensorA; //Encoder Photo Interrupter 1
int sensorB; //Encoder Photo Interrupter 2

int stepOld;
int step;
int counter;

long PulseCount;

#define SENSOR_A 3
#define SENSOR_B 2


//FanControl
int fanN;
int fanE;
int fanS;
int fanW;

Servo EscN;
Servo EscE;
Servo EscS;
Servo EscW;

int fanSpeed;

/*
//Printer
#define TX_PIN 6 // Arduino transmit  YELLOW WIRE  labeled RX on printer
#define RX_PIN 5 // Arduino receive   GREEN WIRE   labeled TX on printer

SoftwareSerial mySerial(RX_PIN, TX_PIN); // Declare SoftwareSerial obj first
Adafruit_Thermal printer(&mySerial);     // Pass addr to printer constructor
*/

//Checking/Comparing sensor state for wind direction
void checkState(){
  sensorA = digitalRead(SENSOR_A);
  sensorB = digitalRead(SENSOR_B);

  if(sensorA == 1 && sensorB == 1){
    step = 0;
    if(stepOld == 1){
      PulseCount--;
    }
    if(stepOld == 3){
      PulseCount++;
    }
    stepOld = 0;
  }

  if(sensorA == 0 && sensorB == 1){
    step = 1;
    if(stepOld == 2){
      PulseCount--;
    }
    if(stepOld == 0){
      PulseCount++;
    }
    stepOld = 1;
  }

  if(sensorA == 0 && sensorB== 0){
    step = 2;
    if(stepOld == 3){
      PulseCount--;
    }
    if(stepOld == 1){
      PulseCount++;
    }
    stepOld = 2;
  }

  if(sensorA == 1 && sensorB == 0){
    step = 3;
    if(stepOld == 0){
      PulseCount--;
    }
    if(stepOld == 2){
      PulseCount++;
    }
    stepOld = 3;
  }

}


void setup() {
  
  Serial.begin(115200);
  Serial.print("                ");
  Serial.print("                ");

  //Direction
  attachInterrupt(0, checkState, CHANGE);
  attachInterrupt(1, checkState, CHANGE);

  PulseCount = 0;
  
  //Speed
  pinMode (20, INPUT);
  attachInterrupt (digitalPinToInterrupt(20), count, FALLING);
  delay(1000);

  //DC-Motor start
  EscN.attach(6,1000,2000);
  EscE.attach(9,1000,2000);
  EscS.attach(10,1000,2000);
  EscW.attach(11,1000,2000);
  
}

void loop() {

  //Limits number of steps to 32 and if minus jumps back to 
  if (PulseCount > 31) {
      PulseCount = 0; 
    }

    if (PulseCount < 0) {
      PulseCount = 31; 
    }

  //Switch-case for wind direction
  Serial.print("Wind-direction :  ");
  
  switch (PulseCount) {

    case 31:
    case 0:
    case 1:
    case 2:
    Serial.println("NORTH");
    counter = 1;
    break;
    
    case 3:
    case 4:
    case 5:
    case 6:
    Serial.println("NORTH-EAST");
    counter = 2;
    break;
    
    case 7:
    case 8:
    case 9:
    case 10:
    Serial.println("EAST");
    counter = 3;
    break;
    
    case 11:
    case 12:
    case 13:
    case 14:
    Serial.println("SOUTH-EAST");
    counter = 4;
    break;
    
    case 15:
    case 16:
    case 17:
    case 18:
    Serial.println("SOUTH");
    counter = 5;
    break;
    
    case 19:
    case 20:
    case 21:
    case 22:
    Serial.println("SOUTH-WEST");
    counter = 6;
    break;
    
    case 23:
    case 24:
    case 25:
    case 26:
    Serial.println("WEST");
    counter = 7;
    break;
    
    case 27:
    case 28:
    case 29:
    case 30:
    Serial.println("NORTH-WEST");
    counter = 8;
    break;
  }

  serial_Print();

  if (millis() - millisBefore > 1000) {
    rpm = (holes / 12.0) * 60;
    holes = 0;
    millisBefore = millis();
  }
  delay(500);


  fan_Control();

  /*
  thermalPrint();
  */
}

//Print Wind Speed
void serial_Print() {
  Serial.print("Wind-speed   : ");
  Serial.print(rpm);
  Serial.println(" RPM");
  Serial.println("     ");
}

//Speed Hole Count
void count() {
  holes++;
}

//Fan Control
void fan_Control() {

  fanSpeed = map(rpm, 0, 400, 0, 60); //Mapping fan speed

  switch (counter) {

    case 1:
    fanN = fanSpeed;
    EscN.write(fanN);

    EscE.write(0);
    EscS.write(0);
    EscW.write(0);
    
    Serial.print("FanN:  ");
    Serial.println(fanN);
    break;
    
    case 2:
    fanN = fanSpeed/2;
    fanE = fanSpeed/2;
    EscN.write(fanN);
    EscE.write(fanE);

    EscS.write(0);
    EscW.write(0);
    
    Serial.print("FanN:  ");
    Serial.println(fanN);
    Serial.print("FanE:  ");
    Serial.println(fanE);
    break;
    
    case 3:
    fanE = fanSpeed;
    EscE.write(fanE);

    EscS.write(0);
    EscW.write(0);
    EscN.write(0);
    
    Serial.print("FanE:  ");
    Serial.println(fanE);
    break;
    
    case 4:
    fanE = fanSpeed/2;
    fanS = fanSpeed/2;
    EscE.write(fanE);
    EscS.write(fanS);

    EscW.write(0);
    EscN.write(0);
    
    Serial.print("FanE:  ");
    Serial.println(fanE);
    Serial.print("FanS:  ");
    Serial.println(fanS);
    break;
    
    case 5:
    fanS = fanSpeed;
    EscS.write(fanS);

    EscW.write(0);
    EscN.write(0);
    EscE.write(0);
    
    Serial.print("FanS:  ");
    Serial.println(fanS);
    break;
    
    case 6:
    fanS = fanSpeed/2;
    fanW = fanSpeed/2;
    EscS.write(fanS);
    EscW.write(fanW);

    EscN.write(0);
    EscE.write(0);
    
    Serial.print("FanS:  ");
    Serial.println(fanS);
    Serial.print("FanW:  ");
    Serial.println(fanW);
    break;
    
    case 7:
    fanW = fanSpeed;
    EscW.write(fanW);
    
    EscN.write(0);
    EscE.write(0);
    EscS.write(0);
    
    Serial.print("FanW:  ");
    Serial.println(fanW);
    break;
    
    case 8:
    fanW = fanSpeed/2;
    fanN = fanSpeed/2;
    EscW.write(fanW);
    EscN.write(fanN);
    
    EscE.write(0);
    EscS.write(0);
    
    Serial.print("FanW:  ");
    Serial.println(fanW);
    Serial.print("FanN:  ");
    Serial.println(fanN);
    break;
  
  }
}
/*

//Reading the Air Quality Sensors
void airQuality() {
    
  
}

//Printing the Air Quality
void thermalPrint() {
  
  
}

//Cutting the paper
void printerCut() {
    
  
}
*/



Experiments

Accelerometer Experiments

In my first experiment, I used an accelerometer to measure a specific angle on the X, Y and Z axes. I thought that it could be useful to capture the wind direction, but seemed a bit boring then.

#include <Wire.h>
#include <LiquidCrystal.h>

LiquidCrystal lcd(12, 11, 7, 8, 9, 10); // RS, E, D4, D5, D6, D7

int ADXL345 = 0x53;                     

float X_out, Y_out, Z_out;
float roll,pitch,rollX,pitchY,rollF,pitchF=0;


void setup() {
  
  //initialise tilt sensor
  Serial.begin(9600);                  
  Wire.begin();
  Wire.beginTransmission(ADXL345);
  Wire.write(0x2D);
  Wire.write(8);
  Wire.endTransmission();
  delay(100);

  //X-axis cal
  Wire.beginTransmission(ADXL345);
  Wire.write(0x1E);  // X-axis offset register
  Wire.write(1);
  Wire.endTransmission();
  delay(100);
  
  
  //Y-axis cal
  Wire.beginTransmission(ADXL345);
  Wire.write(0x1F); // Y-axis offset register
  Wire.write(-2);
  Wire.endTransmission();
  delay(100);

  
  //Z-axis cal
  Wire.beginTransmission(ADXL345);
  Wire.write(0x20); // Z-axis offset register
  Wire.write(-2);
  Wire.endTransmission();
  delay(100);
  
}

void loop() {
  Wire.beginTransmission(ADXL345);
  Wire.write(0x32);
  Wire.endTransmission(false);
  Wire.requestFrom(ADXL345, 6, true);
  X_out = ( Wire.read() | Wire.read() << 8);
  X_out = X_out/256;
  Y_out = ( Wire.read() | Wire.read() << 8);
  Y_out = Y_out/256;
  Z_out = ( Wire.read() | Wire.read() << 8);
  Z_out = Z_out/256;

  Serial.println("RAW: ");
  Serial.print("Xa= ");
  Serial.print(X_out);
  Serial.print("   Ya= ");
  Serial.print(Y_out);
  Serial.print("   Za= ");
  Serial.println(Z_out);
  Serial.println("  ");
  delay(200);

  roll = atan(Y_out / sqrt(pow(X_out, 2) + pow(Z_out, 2))) * 180 / PI;
  pitch = atan(-1 * X_out / sqrt(pow(Y_out, 2) + pow(Z_out, 2))) * 180 / PI;
  // Low-pass filter
  rollX = 0.94 * rollX + 0.06 * roll;
  pitchY = 0.94 * pitchY + 0.06 * pitch;
  
  lcd.begin(8, 2);
  lcd.print("X: ");
  lcd.print(rollX+6, 0);
  lcd.write((char)0b11011111);
  lcd.setCursor(0,1);
  lcd.print("Y: ");
  lcd.print(pitchY+1, 0);
  lcd.write((char)0b11011111);
  delay(200);

  Serial.println("FINAL: ");
  Serial.print("X: ");
  Serial.print(rollX+6, 0);
  Serial.print("˚");
  Serial.print("    Y: ");
  Serial.print(pitchY+1, 0);
  Serial.println("˚");
  Serial.println("–––––––––––––––––––––––––––––––––––––––");
  delay(200);
}


Rotary Encoder

In this experiment I built an eight step rotary encoder with photo interrupters. It is used to read forward and backward steps. With these data I am able to read a direction, in my case, the direction the wind is blowing.


First Code (not working properly at this stage)

int sensorA;
int sensorB;

int stepOld;
int step;

long PulseCount;

#define SENSOR_A 4
#define SENSOR_B 2

void checkState(){
  sensorA = digitalRead(SENSOR_A);
  sensorB = digitalRead(SENSOR_B);

  if(sensorA == 1 && sensorB == 1){
    step = 0;
    if(stepOld == 1){
      PulseCount--;
    }
    if(stepOld == 3){
      PulseCount++;
    }
    stepOld = 0;
  }

  if(sensorA == 0 && sensorB == 1){
    step = 1;
    if(stepOld == 2){
      PulseCount--;
    }
    if(stepOld == 0){
      PulseCount++;
    }
    stepOld = 1;
  }

  if(sensorA == 0 && sensorB== 0){
    step = 2;
    if(stepOld == 3){
      PulseCount--;
    }
    if(stepOld == 1){
      PulseCount++;
    }
    stepOld = 2;
  }

  if(sensorA == 1 && sensorB == 0){
    step = 3;
    if(stepOld == 0){
      PulseCount--;
    }
    if(stepOld == 2){
      PulseCount++;
    }
    stepOld = 3;
  }

}

void setup() {
  
  Serial.begin(115200);
  Serial.print("                ");
  Serial.print("                ");

  attachInterrupt(0, checkState, CHANGE);
  attachInterrupt(1, checkState, CHANGE);

  PulseCount = 0;
}

void loop() {
  Serial.print("Steps:");
  if(PulseCount > -1){
    Serial.print(" ");
  }

  if(PulseCount < 10 && PulseCount > -10){
    Serial.print(" ");
  }

  if(PulseCount < 100 && PulseCount > -100){
    Serial.print(" ");
  }

  Serial.print(PulseCount);
  if(sensorA == 1){
    Serial.println("  HIGH");
  }
  else{
    Serial.println("  LOW ");
  }

  if(sensorB == 1){
    Serial.println("            HIGH");
  }
  else{
    Serial.println("            LOW ");
  }

}


Concept sketch

Inspired by the yearly happening Sisyphean task of sweeping leaves and get them blown away again by the wind. In this installation wind is captured outdoors and will be transmitted and reproduced in a round room. Multiple fans are blowing receipts through a room in the direction and the speed from the wind outside. The fans are aligned in a circle, which reflects the pattern in which the wind is captured. The receipts are printed with nonsense information, which on one hand represent the leaves, but also address the issue of a senseless environmental pollution.

‘’Technical’’ To capture the wind speed and and the direction, a DIY anemometer is built. For both, photo interrupters are used. To measure the wind speed, a slotted disk is used to measure the amount of steps (on/off) in a certain time and then calculated to rpm, which will be send to control the speed of the fans. For capturing the direction, a rotary encoder is built with two photo interrupters and also a disk, that has eight steps (for eight wind directions).


In the final result, the use of an Arduino Mega is necessary to provide enough digital inputs that support interrupts, but also enough outputs for the fans. For the fans, brushless motors are used, that are also very common in drones, e-bikes, etc. They are controlled with motor drivers and powered by a power supply unit.

In this class only a small scale prototype is built, with computer fans.

File:rotary1.JPG

Next steps: get the rotary encoder working, with interrupts and roll-overs, get the "tachometer" working and connect them to computer fans, to control them.