0

Artificial Halo Machine - Random Walk / Reorientation Device
Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.

Artificial Halo Machine - Random Walk / Reorientation Device

by MSelmke on Mon Dec 31, 2018 11:36 am

Using an Arduino Microcrontroller (https://www.adafruit.com/category/17), 2 Adafruit Motorshields V2 (https://www.adafruit.com/product/1438), and 3 Stepper Motors (NEMA-17-sized, https://www.adafruit.com/product/324), I have created a halo machine: It is a device which randomly reorients a sphere placed on top of the 3 motor-axes which make an angle of 120° relative to each other. Placing a prism inside a hollow thin-walled sphere, this device can sample all prism orientations and will generate an artificial 22°-ring halo (for the physics, see the publication below or https://www.atoptics.co.uk/halo/circ1.htm) (for glass: 39°-ring halo) around the direct transmission direction of parallel incident light.

Pictures: https://photonicsdesign.jimdo.com/physics-at-home/ (scroll down to the section "Artificial 22°-halo machine")
Publication: "Artificial Halos", American Journal of Physics, Vol. 83, Issue 9, 751-760, M. Selmke, 2015. (referred to as Selmke2015 below, URL: https://aapt.scitation.org/doi/10.1119/1.4923458, downloadable from my webpage: https://photonicsdesign.jimdo.com/publications/)
Movies / Videos: https://aapt.scitation.org/doi/suppl/10.1119/1.4923458 (e.g. iterative accumulation of images; mergeanimation.mov (1 MB), halomachine.mov (4 MB))

Instructions (see also Selmke2015)
1) Set up your Arduino, https://learn.adafruit.com/adafruit-motor-shield-v2-for-arduino/install-headers
2) Follow the motor shield stacking install instructions first (especially the jumper as written below for AFMStop / AFMSbot):
2a) Install bottom shield, https://learn.adafruit.com/adafruit-motor-shield-v2-for-arduino/install-headers
2b) Install top shield, https://learn.adafruit.com/adafruit-motor-shield-v2-for-arduino/stacking-shields
3) Then install software: https://learn.adafruit.com/adafruit-motor-shield-v2-for-arduino/install-software
4) Set the VIN jumper to run the shields on Arduino's DC Barrel Jack, see https://learn.adafruit.com/adafruit-motor-shield-v2-for-arduino/install-software
5) Connect all 3 stepper motors as shown in Selmke2015, see also below in code definitions of *myStepper#. Arrange and fix the stepper motors in a triangle as shown in Selmke2015. Beware of the correct coil wirings per stepper as described in the shield instructions linked above.
6) Attach 5mm to 10mm Flex Shaft Couplers (https://www.adafruit.com/product/1177) to the motor axes and equip them with 18mm diameter rubber O-rings.
7) Optional: install LEDs with resistors as shown in images of Selmke2015, i.e. between pins 5&6 and GND. Otherwise: Set the variable LEDm=0 in the code.
8) Add power supply (https://www.adafruit.com/product/63) to Arduino's DC Barrel. I found the device also to work with a 9V block battery (https://www.adafruit.com/product/67).
9) Upload Arduino code as provided below.
10) Place a sphere on top.

The code below could be further optimized to avoid the slight skidding of the sphere: instead of collective rotation modes of all motors with each having the same rotational speed, the collective modes should rather involve 1 stepper at full speed and 2 steppers with half the rotational speed (credit goes to Gautier Corgne for this idea)...

Code: Select all | TOGGLE FULL SIZE
#include <Wire.h>
#include <Adafruit_MotorShield.h> //includes the previously installed Motor Shield library
#include "utility/Adafruit_PWMServoDriver.h"

Adafruit_MotorShield AFMSbot(0x60); // Default address, no jumpers (name bottom shield)
Adafruit_MotorShield AFMStop(0x61); // Rightmost jumper closed (name top shield)

// On the top/upper motor shield, connect two steppers, each with 200 steps
Adafruit_StepperMotor *myStepper2 = AFMStop.getStepper(200, 1); //(name stepper2: Fig.9 Selmke2015: top right / M1 & M2, top shield)
Adafruit_StepperMotor *myStepper3 = AFMStop.getStepper(200, 2); //(name stepper3: Fig.9 Selmke2015: top left / M3 & M4, top shield)

// On the bottom motor shield connect a stepper to port M3/M4 with 200 steps
Adafruit_StepperMotor *myStepper1 = AFMSbot.getStepper(200, 2); //(name stepper1: Fig.9 Selmke2015: bottom left / M3 & M4, bottom shield)

//LEDs: Connect 2 LEDs between Digital I/O Pins 5&6 and Gnd (optional)
int LEDm=1; //set to zero to keep leds dark, to 1 to light them according to angular step magnitude
int rpm=20;
int MaxStep=555;

void setup() {
  pinMode(5, OUTPUT); //LED 1 pin
  pinMode(6, OUTPUT); //LED 2 pin
 
  while (!Serial);
  Serial.begin(9600); // set up Serial library at 9600 bps
  Serial.println("Halomator 2015");
 
  //initialize seed for random number generation using open input port voltage
  randomSeed(analogRead(0));

  AFMSbot.begin(); // Start the bottom shield
  AFMStop.begin(); // Start the top shield
 
  myStepper1->setSpeed(rpm);
  myStepper2->setSpeed(rpm);
  myStepper3->setSpeed(rpm);
}

int i,x,y,z;
void loop() {
  //x,y,z are the three axis. Each axis moves 3 steppers in synch (defining a collective rotation "mode" to affect 1 type of movement of the sphere).
  x = round(random(-MaxStep,MaxStep));
    Movex(x);
    delay(100);
  y = round(random(-MaxStep,MaxStep));
    Movey(y);
    delay(100);
  z = round(random(-MaxStep,MaxStep));
    Movez(z);
    delay(100);
}

//define collective rotation modes; negative values reverse all directions in mode
void Movex(int x) {
 if (x>= 0) {
   analogWrite(6, round(LEDm*255*abs(x)/MaxStep));
   for (i=0; i<abs(x); i++) {
     myStepper1->onestep(FORWARD, MICROSTEP);
     myStepper2->onestep(FORWARD, MICROSTEP);
     myStepper3->onestep(BACKWARD, MICROSTEP);
   }
   digitalWrite(6, LOW);
 } else {
   analogWrite(5, round(LEDm*255*abs(x)/MaxStep));
   for (i=0; i<abs(x); i++) {
     myStepper1->onestep(BACKWARD, MICROSTEP); //cf. above: all inverted
     myStepper2->onestep(BACKWARD, MICROSTEP);
     myStepper3->onestep(FORWARD, MICROSTEP);
   } 
   digitalWrite(5, LOW);
 }
}

void Movey(int y) {
 if (y>= 0) {
   analogWrite(6, round(LEDm*255*abs(y)/MaxStep));
   for (i=0; i<abs(y); i++) {
     myStepper1->onestep(BACKWARD, MICROSTEP);
     myStepper2->onestep(FORWARD, MICROSTEP);
     myStepper3->onestep(FORWARD, MICROSTEP);
   }
   digitalWrite(6, LOW);
 } else {
   analogWrite(5, round(LEDm*255*abs(y)/MaxStep));
   for (i=0; i<abs(y); i++) {
     myStepper1->onestep(FORWARD, MICROSTEP);
     myStepper2->onestep(BACKWARD, MICROSTEP);
     myStepper3->onestep(BACKWARD, MICROSTEP);
   } 
   digitalWrite(5, LOW);
 }
}

void Movez(int z) {
 if (z>= 0) {
   analogWrite(6, round(LEDm*255*abs(z)/MaxStep));
   for (i=0; i<abs(z); i++) {
     myStepper1->onestep(BACKWARD, MICROSTEP);
     myStepper2->onestep(BACKWARD, MICROSTEP);
     myStepper3->onestep(BACKWARD, MICROSTEP);
   }
   digitalWrite(6, LOW);
 } else {
   analogWrite(5, round(LEDm*255*abs(z)/MaxStep));
   for (i=0; i<abs(z); i++) {
     myStepper1->onestep(FORWARD, MICROSTEP);
     myStepper2->onestep(FORWARD, MICROSTEP);
     myStepper3->onestep(FORWARD, MICROSTEP);
   } 
   digitalWrite(5, LOW);
 }
}
Attachments
DSCF4807.jpg
Image of the Device
DSCF4807.jpg (622.42 KiB) Viewed 152 times
Last edited by MSelmke on Mon Jan 07, 2019 3:47 pm, edited 3 times in total.

MSelmke
 
Posts: 2
Joined: Mon Dec 31, 2018 11:19 am

Re: Artificial Halo Machine - Random Walk / Reorientation De

by Disciple on Tue Jan 01, 2019 4:58 am

Interesting project. Do any videos exist? I imagine a time-lapse of samples gradually building up a pattern, like electron hits in the double slit experiment.

Hallelujah!
Disciple

Disciple
 
Posts: 674
Joined: Tue Jan 06, 2015 8:13 pm

Re: Artificial Halo Machine - Random Walk / Reorientation De

by MSelmke on Tue Jan 01, 2019 7:00 am

Hello Disciple,

yes, videos like you suggest exist as part of the supplementary material to the article on the publisher's website. They are accessible for free under the given link next to "Movies / Videos" in my original post.

What would be great would be an extension of this project to work either much faster (accumulation time of the video was a few hours) or precisely controllable, i.e. not a random walk machine but a precise orientation device which would allow to set an arbitrary orientation of a sphere placed on top. That would allow one to create complex halo displays (cf. https://www.atoptics.co.uk/halo/spole.htm) by selectively realizing certain subsets of orientations only. I was also thinking of adding some marker to optically track the orientation of the sphere and the embedded crystal and doing a post-selection of images instead, but never came around doing so.

MSelmke
 
Posts: 2
Joined: Mon Dec 31, 2018 11:19 am

Please be positive and constructive with your questions and comments.