All Day Coding w/Alan

Spent all day Saturday Coding with Alan.  We now have functionality that flashes the LEDs when:

  • There is a hit, or an acceleration event (yellow)
  • There is significant rotation in the X-Axis (red)
  • There is significant rotation in the Y-Axis (blue)
  • There is significant rotation in the Z-Axis (green)
// NeoPixel Ring simple sketch (c) 2013 Shae Erisson
// released under the GPLv3 license to match the rest of the AdaFruit NeoPixel library
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h>
#endif
// Which pin on the Arduino is connected to the NeoPixels?
// On a Trinket or Gemma we suggest changing this to 1
#define PIN            11
// How many NeoPixels are attached to the Arduino?
#define NUMPIXELS      4
//Gyro Threshold?
const int GyroThreshold = 5.5;
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
int delayval = 500; // delay for half a second
int red = 0;
int green = 50;
int blue = 100;
//////////////////////////////
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_LSM303_U.h>
#include <Adafruit_L3GD20_U.h>
#include <Adafruit_9DOF.h>
/* Assign a unique ID to the sensors */
Adafruit_9DOF                dof   = Adafruit_9DOF();
Adafruit_LSM303_Accel_Unified accel = Adafruit_LSM303_Accel_Unified(30301);
Adafruit_LSM303_Mag_Unified   mag   = Adafruit_LSM303_Mag_Unified(30302);
Adafruit_L3GD20_Unified       gyro  = Adafruit_L3GD20_Unified(20);
/* Update this with the correct SLP for accurate altitude measurements */
float seaLevelPressure = SENSORS_PRESSURE_SEALEVELHPA;
/**************************************************************************/
/*!
    @brief  Initialises all the sensors used by this example
*/
/**************************************************************************/
void initSensors()
{
  if (!accel.begin())
  {
¬† ¬† /* There was a problem detecting the LSM303 … check your connections */
¬† ¬† //Serial.println(F(“Ooops, no LSM303 detected … Check your wiring!”));
    while (1);
  }
  if (!mag.begin())
  {
¬† ¬† /* There was a problem detecting the LSM303 … check your connections */
¬† ¬† //Serial.println(“Ooops, no LSM303 detected … Check your wiring!”);
    while (1);
  }
  if (!gyro.begin())
  {
¬† ¬† /* There was a problem detecting the L3GD20 … check your connections */
¬† ¬† Serial.print(“Ooops, no L3GD20 detected … Check your wiring or I2C ADDR!”);
    while (1);
  }
}
/**************************************************************************/
/*!
*/
/**************************************************************************/
void setup(void)
{
  //while (!Serial);
  //Serial.begin(15200);
¬† //sSerial.println(F(“Adafruit 9 DOF Pitch/Roll/Heading Example”)); Serial.println(“”);
  /* Initialise the sensors */
  initSensors();
  ///////////////NeoPixel/////////////
  pixels.begin(); // This initializes the NeoPixel library.
}
/**************************************************************************/
/*!
    @brief  Constantly check the roll/pitch/heading/altitude/temperature
*/
/**************************************************************************/
void loop(void)
{
  sensors_event_t event;
  sensors_event_t mag_event;
  sensors_vec_t   orientation; // v[3] floats, x,y,z floats, roll/pitch/heading floats; .status signedbyte
  // if (dof.accelGetOrientation(&event, &orientation))
¬† /* Leave Uncommented unless testing ‘orientation’ should have valid .roll and .pitch fields */
  /*
¬† ¬† Serial.print(F(“Roll: “));
    Serial.print(orientation.roll);
¬† ¬† Serial.print(F(“; “));
¬† ¬† Serial.print(F(“Pitch: “));
    Serial.print(orientation.pitch);
¬† ¬† Serial.print(F(“; “));
  */
¬† //Serial.print(F(“A0”));
  ////Acceleratin Event
  ///Normal Lighting Up for no event
  for (int j = 0; j < 256; j++) {
    for (int i = 0; i < NUMPIXELS; i++) {
      // pixels.Color takes RGB values, from 0,0,0 up to 255,255,255
      pixels.setPixelColor(i, pixels.Color(j, 0, 255 Рj)); // Moderately bright green color.
    }
    pixels.show(); // This sends the updated pixel color to the hardware.
    //Serial.println(j);
    while (nonblocking_delay(50)) {
      accel.getEvent(&event);
      float the_accel = event.acceleration.v[0];
      gyro.getEvent(&event);
      float gyro_max;
      gyro_max = max( abs(event.gyro.x), abs(event.gyro.y));
      gyro_max = max( abs(gyro_max), abs(event.gyro.z));
¬† ¬† ¬† Serial.print(GyroThreshold); Serial.print(” “);
¬† ¬† ¬† Serial.print(abs(event.gyro.x)); Serial.print(” “);
¬† ¬† ¬† Serial.print(abs(event.gyro.y)); Serial.print(” “);
¬† ¬† ¬† Serial.print(abs(event.gyro.z)); Serial.print(” “);
¬† ¬† ¬† Serial.print(gyro_max); Serial.print(” “);
      Serial.println();
      //Serial.println(the_accel);
      //Serial.println(gyro_max);
¬† ¬† ¬† /*Serial.println(F(“Max:”));
        Serial.print(gyro_max);
¬† ¬† ¬† ¬† ¬† Serial.print(F(“; “));
¬† ¬† ¬† ¬† Serial.print(F(“X:”));
        Serial.print(event.gyro.x);
¬† ¬† ¬† ¬† ¬† Serial.print(F(“; “));
¬† ¬† ¬† ¬† Serial.print(F(“Y:”));
        Serial.print(event.gyro.y);
¬† ¬† ¬† ¬† ¬† Serial.print(F(“; “));
¬† ¬† ¬† ¬† Serial.print(F(“Z:”));
        Serial.print(event.gyro.z);
¬† ¬† ¬† ¬† ¬† Serial.print(F(“; “)); */
      if (the_accel > 18) {
        run_excitementrgb(255,255,0);
      }
      else if (gyro_max >= GyroThreshold) {
        // run_excitement2(); {
¬† ¬† ¬† ¬† // gyro dominant axis, but “precession…”
        if ( abs(event.gyro.x) > abs(event.gyro.y) && abs(event.gyro.x) > abs(event.gyro.z)) {
          run_excitementrgb(255,0,0);
        }
        else if ( abs(event.gyro.y) > abs(event.gyro.x) && abs(event.gyro.y) > abs(event.gyro.z)) {
          run_excitementrgb(0,255,0);
        }
        else if ( abs(event.gyro.z) > abs(event.gyro.y) && abs(event.gyro.z) > abs(event.gyro.x)) {
          run_excitementrgb(0,0,255);
        }
      }
    }
  }
  for (int i = 0; i < NUMPIXELS; i++) {
    pixels.setPixelColor(i, pixels.Color(0, 0, 0)); // Off
  }
   pixels.show();
  delay(100);
}
void run_excitementrgb(int r, int g, int b) {
  unsigned long timer = millis() + 5000; // run this pattern for this long
  int which = 1; // 1 means on
  while ( millis() < timer) {
    for (int i = 0; i < NUMPIXELS; i++) {
      // pixels.Color takes RGB values, from 0,0,0 up to 255,255,255
      if (which) {
        pixels.setPixelColor(i, pixels.Color(r, g, b)); // Moderately bright red color.
      }
      else {
        pixels.setPixelColor(i, pixels.Color(0, 0, 0)); // off
      }
    }
    pixels.show(); // This sends the updated pixel color to the hardware.
    delay(50);
¬† ¬† which = !which; // 1,0,1,0,1…
  }
}
void run_excitement() {
  //Serial.println(the_accel);
  ///////////////NeoPixel///////////////////////
  for (int i = 0; i < NUMPIXELS; i++) {
    // pixels.Color takes RGB values, from 0,0,0 up to 255,255,255
    pixels.setPixelColor(i, pixels.Color(0, 0, 255)); // Moderately bright red color.
    //pixels.setPixelColor(i, pixels.Color(0,0,0)); // Off
    // pixels.show();
  }
  delay(10);
  pixels.show(); // This sends the updated pixel color to the hardware.
  //Serial.println(j);
  delay(5000); // Delay for a period of time (in milliseconds).
}
boolean nonblocking_delay(int ms) {
  // will return true while the timer is running
  static unsigned long timer = 0;
¬† // “first” time, setup
  if (timer == 0) {
    timer = millis() + ms;
    return true;
  }
  if (millis() < timer) {
¬† ¬† // delay hasn’t expired
    return true;
  }
  timer = 0; // for next time
  return false;
}

Soldering, Suffering, and Progress

Yesterday’s working session was painful (hardware debugging always is) but I managed to make some good progress:

First, I was able to test out the working concept with an Arduino UNO (that is, hook up the accelerator to the arduino, and receive pitch, yaw, roll, and acceleration data as I physically moved it around:

img_2125

Step two was to solder up everything using the Arduino Feather, and then start digging into the software dev.  In short, I was able to get everything connected and talking and, when an specific high acceleration event occurs (that is, the hitting of the beach ball) turn on the LEDs:

img_2128

I’m a little behind as I wanted to have my software more flushed out at this point, but happy that I at least didn’t screw anything up on the hardware side (despite my best efforts)

 

TimeLine

NOTE: In the effort of Time, I am starting the prototyping process by mapping the motion sensor inputs (x, y, z, roll, pitch, yaw, etc) to lights inside the beach ball.  Assuming I can get this working, I will then work on sending the exact same signals via WiFi and Midi.

  • 2 November:
    • Finalize Design (Electrical and Hardware)
    • Finalize Electrical BOM
    • Order Electrical Components
  • 9 November
    • Receive Electrical Components and Solder them Together
    • Cut Central Styrofoam core and place them together
    • Confirm appropriate Connections
  • 16 November
    • Write and Test Arduino Code
    • Prove Out Working Lights
  • 30 November
    • Finalize Hardware BOM (Beach Ball and Cement)
    • Order Components
  • 7 December
    • Assemble Full unit (Core, Sock, and Beach Ball)
    • Test it Out
    • Build Display
  • 14 December (ie if time allows)
    • Work on MIDI communication in addition to lights