Code for LSM303

EL Wire/Tape/Panels, LEDs, pixels and strips, LCDs and TFTs, etc products from Adafruit

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
User avatar
niknak35
 
Posts: 53
Joined: Sat Apr 26, 2014 10:59 pm

Code for LSM303

Post by niknak35 »

Hi
I'm trying to get a FLORA LSM303 with a Flora to drive a 16x16 LED matrix. I want the Accelerometer to drive the RGB colors as it moves. I've had something similar working with a 345 Accelerometer but am having trouble with LSM303 which is below. I fairly new to code! Could you help me get to a similar stage with the LSM303?
What would be awesome if there was any code out there that could simulate gravity with light like this
http://www.fashionotes.com/content/2012 ... light-hat/

I'd like to also trigger some animations with the LSM303 using the forces. ie sudden movements trigger colour changes and animations.
Thanks
Nick

Code: Select all

#include <Adafruit_NeoPixel.h>
 
#define PIN      6
#define N_LEDS 16
 
Adafruit_NeoPixel strip = Adafruit_NeoPixel(N_LEDS, PIN, NEO_GRB + NEO_KHZ800);
const int RedPin = 3;
const int GreenPin = 5;
const int BluePin = 6;

const int sensorPinRed = A3;
const int sensorPinGreen = A2;
const int sensorPinBlue = A1;

const int minReading = 490;
const int maxReading =560;
const int BlueAdj = 50;

int analogValue = 0;
int x; 
int y; 
int z; 

void setup()
{ 
  Serial.begin(9600); 
  strip.begin();
  strip.show();
} 
void loop() 
{
  //Red
  analogValue = analogRead(sensorPinRed);
  analogValue = constrain(analogValue, minReading, maxReading);
  x = map(analogValue, minReading, maxReading, 0, 255);
  
  Serial.print("analogValue Red = " );                       
  Serial.print(x);
  
//Green
  analogValue = analogRead(sensorPinGreen);
  analogValue = constrain(analogValue, minReading, maxReading);
  y = map(analogValue, minReading, maxReading, 0, 255);
  Serial.print("  Green = " );                       
  Serial.print(y);
  
  //Blue
  analogValue = analogRead(sensorPinBlue);
  analogValue = analogValue-BlueAdj;
  analogValue = constrain(analogValue, minReading, maxReading);
  z = map(analogValue, minReading, maxReading, 0, 255);
  Serial.print("  Blue = " );     
  Serial.println(z);

  strip.setPixelColor(random(16), x, y, z);// red x
  strip.show();
    
}

User avatar
adafruit_support_bill
 
Posts: 88086
Joined: Sat Feb 07, 2009 10:11 am

Re: Code for LSM303

Post by adafruit_support_bill »

I've had something similar working with a 345 Accelerometer but am having trouble with LSM303 which is below. I fairly new to code! Could you help me get to a similar stage with the LSM303?
The best place to start is with the example code from the LSM303DLHC library: https://github.com/adafruit/Adafruit_LSM303DLHC

Since the LSM303 is a digital sensor, you need to replace your analogReads with calls to accel.getEvent(&event); Once you make that call, your x, y and z data will be available in event.acceleration.x, event.acceleration.y and event.acceleration.z. Form there, you can use them just like the analog values you read from the 345.
What would be awesome if there was any code out there that could simulate gravity with light like this
http://www.fashionotes.com/content/2012 ... light-hat/
To simulate something physical like gravity, you create a model of it in code and let the measured forces act on the model. We call this a "Physics Engine". For an example of a physics engine using the LSM303, check out this project: https://learn.adafruit.com/steam-punk-goggles

User avatar
niknak35
 
Posts: 53
Joined: Sat Apr 26, 2014 10:59 pm

Re: Code for LSM303

Post by niknak35 »

Thanks So Much For That! I love the Steampunk Code and will modify it to drive to Strips of Neopixels wrapped around a ball. (I'm making a LED Jelly Fish for kids to play with) Is there a way to get a second pendulum opposite each pendulum? Also i'd like to add a 'Force' gesture. When the Jelly fish is shaken it lights up with a different animation. Any pointers would be awesome!
Cheers
Nick

User avatar
adafruit_support_bill
 
Posts: 88086
Joined: Sat Feb 07, 2009 10:11 am

Re: Code for LSM303

Post by adafruit_support_bill »

Is there a way to get a second pendulum opposite each pendulum?
That should be possible. In the goggle project there is really only one pendulum modeled, then it is replicated in the two lenses. If you look at "Mirror Mode", the second pendulum is just the same pendulum drawn in reverse.
Also i'd like to add a 'Force' gesture. When the Jelly fish is shaken it lights up with a different animation.
You'll need to figure out what kinds of gesture you want to use to trigger that. For the goggles there is the "CheckForNods()" function to trigger mode switches and the spin-up/spin-down effect. That is based on both time and the direction of the force. You could modify that to test just for the magnitude of the force. To calculate the magnitude of the force from all three axis is: sqrt(event.acceleration.x**2 + event.acceleration.y**2 + event.acceleration.z**2);

User avatar
niknak35
 
Posts: 53
Joined: Sat Apr 26, 2014 10:59 pm

Re: Code for LSM303

Post by niknak35 »

Thanks Bill
I've managed to get to opposite pendulums happening. I've tried replacing the Nods with Force but it seems to activate all the time. Can you check my code and see if i'm on the right path?

Code: Select all

// Googly Eye Goggles
// By Bill Earl
// For Adafruit Industries
//
// The googly eye effect is based on a physical model of a pendulum.
// The pendulum motion is driven by accelerations in 2 axis.
// Eye color varies with orientation of the magnetometer

#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_LSM303_U.h>
#include <Adafruit_NeoPixel.h>

#define PIN 6

// We could do this as 2 16-pixel rings wired in parallel.
// But keeping them separate lets us do the right and left
// eyes separately if we want.

Adafruit_NeoPixel strip = Adafruit_NeoPixel(39, PIN, NEO_GRB + NEO_KHZ800);
int x; 
int y; 
int z;
int f;

Adafruit_LSM303_Accel_Unified accel = Adafruit_LSM303_Accel_Unified(54321);
Adafruit_LSM303_Mag_Unified mag = Adafruit_LSM303_Mag_Unified(12345);
 
float pos = 0;  // Starting center position of pupil
float posB = 0;  // Starting center position of pupil
float increment = 2 * 3.14159 / 39; // distance between pixels in radians
float incrementB = 2 * 3.14159 / 39; // distance between pixels in radians
float MomentumH = 0; // horizontal component of pupil rotational inertia
float MomentumV = 0; // vertical component of pupil rotational inertia

// Tuning constants. (a.k.a. "Fudge Factors)  
// These can be tweaked to adjust the liveliness and sensitivity of the eyes.
const float friction = 0.95; // frictional damping constant.  1.0 is no friction.
const float swing = 60;  // arbitrary divisor for gravitational force
const float gravity = 200;  // arbitrary divisor for lateral acceleration
const float nod = 7.5; // accelerometer threshold for toggling modes

long nodStart = 0;
long nodTime = 2000;

bool antiGravity = false;  // The pendulum will anti-gravitate to the top.
bool mirroredEyes = false; // The left eye will mirror the right.

const float halfWidth = 1.25; // half-width of pupil (in pixels)

// Pi for calculations - not the raspberry type
const float Pi = 3.14159;

void setup(void) 
{
   strip.begin();
   strip.show(); // Initialize all pixels to 'off'  sensor_t sensor;

   // Initialize the sensors
   accel.begin();
   mag.begin();
   
   resetModes();
}

// main processing loop
void loop(void) 
{
   // Read the magnetometer and determine the compass heading:
   sensors_event_t event; 
   mag.getEvent(&event);
   x=event.acceleration.x;
   y=event.acceleration.y;
    z=event.acceleration.z;
   f= sqrt(x*x+y*y+z*z);

   // Calculate the angle of the vector y,x from magnetic North
   float heading = (atan2(event.magnetic.y,event.magnetic.x) * 180) / Pi;

   // Normalize to 0-360 for a compass heading
   if (heading < 0)
   {
      heading = 360 + heading;
   }

   // Now read the accelerometer to control the motion.
   accel.getEvent(&event);

   // Check for mode change commands
   CheckForNods(event);

   // apply a little frictional damping to keep things in control and prevent perpetual motion
   MomentumH *= friction;
   MomentumV *= friction;

   // Calculate the horizontal and vertical effect on the virtual pendulum
   // 'pos' is a pixel address, so we multiply by 'increment' to get radians.
   float TorqueH = cos(pos * increment);  // peaks at top and bottom of the swing
   float TorqueV = sin(pos * incrementB);    // peaks when the pendulum is horizontal

   // Add the incremental acceleration to the existing momentum
   // This code assumes that the accelerometer is mounted upside-down, level
   // and with the X-axis pointed forward.  So the Y axis reads the horizontal
   // acceleration and the inverse of the Z axis is gravity.
   // For other orientations of the sensor, just change the axis to match.
   MomentumH += TorqueH * event.acceleration.y / swing;
   if (antiGravity)
   {
     MomentumV += TorqueV * event.acceleration.z / gravity;
   }
   else
   {
     MomentumV -= TorqueV * event.acceleration.z / gravity;
   }

   // Calculate the new position
   pos += MomentumH + MomentumV;
   
   // handle the wrap-arounds at the top
   while (round(pos) < 0) pos += 39.0;
   while (round(pos) > 38) pos -= 39.0;

   // Now re-compute the display
   for (int i = 0; i < 39; i++)
   {
      // Compute the distance bewteen the pixel and the center
      // point of the virtual pendulum.
      float diff = i - pos;

      // Light up nearby pixels proportional to their proximity to 'pos'
      if (fabs(diff) <= halfWidth) 
      {
         uint32_t color;
         float proximity = halfWidth - fabs(diff) * 200;

         // pick a color based on heading & proximity to 'pos'
         color = selectColor(heading, proximity);
         
         // do both eyes
         strip.setPixelColor(i, color);
         if (mirroredEyes)
         {
           strip.setPixelColor(38 - i, color);
         }
         else
         {
           strip.setPixelColor(38 - i, color);
         }
      }
      else // all others are off
      {
         strip.setPixelColor(i, 0);
         if (mirroredEyes)
         {
           strip.setPixelColor(38 - i, 0);
         }
         else
         {
           strip.setPixelColor(38 - i, 0);
         }
      }
   }
   // Now show it!
   strip.show();
}

   

// choose a color based on the compass heading and proximity to "pos".
uint32_t selectColor(float heading, float proximity)
{
     uint32_t color;

     // Choose eye color based on the compass heading
     if (heading < 30)
     {
        color = strip.Color(255, 0, 0);
     }
     else if (heading < 60)
     {
        color = strip.Color(0, 255, 255);
     }
     else if (heading < 90)
     {
        color = strip.Color(127, 0, 255);
     }
     else if (heading < 120)
     {
        color = strip.Color(128, 255, 0);
     }
     else if (heading < 150)
     {
        color = strip.Color(255, 0, 128);
     }
     else if (heading < 180)
     {
        color = strip.Color(0, 255, 64);
     }
     else if (heading < 210)
     {
        color = strip.Color(0, 21, 255);
     }
     else if (heading < 240)
     {
        color = strip.Color(255, 191, 0);
     }
     else if (heading < 270)
     {
        color = strip.Color(255, 0, 0);
     }
     else if (heading < 300)
     {
        color = strip.Color(0, 255, 255);
     }
     else if (heading < 330)
     {
        color = strip.Color(127, 0, 255);
     }
     else // 300-360
     {
        color = strip.Color(128, 255, 0);
     }
}

// monitor orientation for mode-change 'gestures'
void CheckForNods(sensors_event_t event)
{
   if (f > 12)
   {
     if (millis() - nodStart > nodTime)
     {
       antiGravity = false;  
       nodStart = millis(); // reset timer     
       spinDown();
     }
   }
   else if (f>20)
   {
     if (millis() - nodStart > nodTime)
     {
       antiGravity = true;  
       spinUpB();
       nodStart = millis(); // reset timer     
     }
   }
   else if (f>30)
   {
     if (millis() - nodStart > nodTime)
     {
       mirroredEyes = false;  
       spinUpB();
       nodStart = millis(); // reset timer     
     }
   }
   else if (f>35)
   {
     if (millis() - nodStart > nodTime)
     {
       mirroredEyes = true;  
       spinUp();
       nodStart = millis(); // reset timer     
      }
   }
   else // no nods in progress
   {
     nodStart = millis(); // reset timer
   }
}

// Reset to default
void resetModes()
{
   antiGravity = false;
   mirroredEyes = false;
   
   /// spin-up
   spin(strip.Color(255,0,0), 1, 500);
   spin(strip.Color(0,255,0), 1, 500);
   spin(strip.Color(0,0,255), 1, 500);
   spinUp();
}

// gradual spin up

void spinUp()
{
   for (int i = 300; i > 0;  i -= 20)
   {
     spin(strip.Color(255,255,255), 1, i);
   }
   pos = 0;
   // leave it with some momentum and let it 'coast' to a stop
   MomentumH = 3;  
}
void spinUpB()
{
   for (int i = 150; i > 0;  i -= 20)
   {
     spin(strip.Color(255,255,255), 1, i);
   }
   pos = 0;
   // leave it with some momentum and let it 'coast' to a stop
   MomentumH = 3;  
}

// Gradual spin down
void spinDown()
{
   for (int i = 1; i < 30; i++)
   {
     spin(strip.Color(0,128,128), 1, i += 20);
   }
   // Stop it dead at the top and let it swing to the bottom on its own
   pos = 0;
   MomentumH = MomentumV = 0;
}

// utility function for feedback on mode changes.
void spin(uint32_t color, int count, int time)
{
  for (int j = 0; j < count; j++)
  {
    for (int i = 0; i < 39; i++)
    {
      strip.setPixelColor(i, color);
      strip.setPixelColor(38 - i, color);
      strip.show();
      delay(max(time / 39, 1));
      strip.setPixelColor(i, 0);
      strip.setPixelColor(38 - i, 0);
      strip.show();
    }
  }
}   
cheers
Nick

User avatar
adafruit_support_bill
 
Posts: 88086
Joined: Sat Feb 07, 2009 10:11 am

Re: Code for LSM303

Post by adafruit_support_bill »

I've tried replacing the Nods with Force but it seems to activate all the time.
Print out the value of 'f' on each pass of the loop to see what the typical values look like. I suspect that you need to set your threshold values higher to avoid constant triggering.

User avatar
niknak35
 
Posts: 53
Joined: Sat Apr 26, 2014 10:59 pm

Re: Code for LSM303

Post by niknak35 »

Thanks! I got that working by removing the timing code for the nods. Is it possible to trigger different animations based on force values? ie a force over 25 starts a different animation. This is the code I have so far.
Cheers

void CheckForNods(sensors_event_t event)
{
if (f > constrain(f, 18, 20))
{
spinDown(); //red

}

else if (f>21)


{

spinUp(); //blue

}

else if (f>25)


{

spinDownB();

}

else if (f>29)
{

{

spinUpB();

}
}
else // no nods in progress
{

}

User avatar
adafruit_support_bill
 
Posts: 88086
Joined: Sat Feb 07, 2009 10:11 am

Re: Code for LSM303

Post by adafruit_support_bill »

The problem is that the force may peak at 25 or more, but it has to pass through lower values to get there. If your code triggers some effect on 21, it will miss the peak at 25+.

Another problem is the way you are using the constrain function here:

Code: Select all

if (f > constrain(f, 18, 20))
{
spinDown(); //red

}
The value of constrain here is limited to the range of 18-20. So any value of f over 18 will trigger the spin down.

User avatar
niknak35
 
Posts: 53
Joined: Sat Apr 26, 2014 10:59 pm

Re: Code for LSM303

Post by niknak35 »

What about firing different animations on a force trigger. ie choose a random animation. Do you have an example of that?
cheers
Nick

User avatar
adafruit_support_bill
 
Posts: 88086
Joined: Sat Feb 07, 2009 10:11 am

Re: Code for LSM303

Post by adafruit_support_bill »

Something like this?

Code: Select all

if (f > 25)
{
   int pattern = random(5);  // choose one of 5 random patterns
   switch (pattern)
   {
       case 0:
           // do pattern 0
           break;
       case 1:
           // do pattern 1
           break;
       case 2:
           // do pattern 2
           break;
       case 3:
           // do pattern 3
           break;
       case 4:
           // do pattern 4
           break;
   }
}

User avatar
niknak35
 
Posts: 53
Joined: Sat Apr 26, 2014 10:59 pm

Re: Code for LSM303

Post by niknak35 »

That looks perfect! I've tried the following code but its not working. What am I missing?

Code: Select all

// Googly Eye Goggles
// By Bill Earl
// For Adafruit Industries
//
// The googly eye effect is based on a physical model of a pendulum.
// The pendulum motion is driven by accelerations in 2 axis.
// Eye color varies with orientation of the magnetometer

#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_LSM303_U.h>
#include <Adafruit_NeoPixel.h>

#define PIN 6

// We could do this as 2 16-pixel rings wired in parallel.
// But keeping them separate lets us do the right and left
// eyes separately if we want.

Adafruit_NeoPixel strip = Adafruit_NeoPixel(39, PIN, NEO_GRB + NEO_KHZ800);
int x; 
int y; 
int z;
int f;
int p;

Adafruit_LSM303_Accel_Unified accel = Adafruit_LSM303_Accel_Unified(54321);
Adafruit_LSM303_Mag_Unified mag = Adafruit_LSM303_Mag_Unified(12345);
 
float pos = 0;  // Starting center position of pupil
float posB = 0;  // Starting center position of pupil
float increment = 2 * 3.14159 / 16; // distance between pixels in radians
float incrementB = 2 * 3.14159 / 16; // distance between pixels in radians
float MomentumH = 0; // horizontal component of pupil rotational inertia
float MomentumV = 0; // vertical component of pupil rotational inertia

// Tuning constants. (a.k.a. "Fudge Factors)  
// These can be tweaked to adjust the liveliness and sensitivity of the eyes.
const float friction = 0.95; // frictional damping constant.  1.0 is no friction.
const float swing = 60;  // arbitrary divisor for gravitational force
const float gravity = 200;  // arbitrary divisor for lateral acceleration
const float nod = 7.5; // accelerometer threshold for toggling modes

long nodStart = 0;
long nodTime = 2000;

bool antiGravity = false;  // The pendulum will anti-gravitate to the top.
bool mirroredEyes = false; // The left eye will mirror the right.

const float halfWidth = 1.25; // half-width of pupil (in pixels)

// Pi for calculations - not the raspberry type
const float Pi = 3.14159;

void setup(void) 
{
  Serial.begin(9600); 
  strip.begin();
   strip.show(); // Initialize all pixels to 'off'  sensor_t sensor;

   // Initialize the sensors
   accel.begin();
   mag.begin();
   
   resetModes();
}

// main processing loop
void loop(void) 
{
   // Read the magnetometer and determine the compass heading:
   sensors_event_t event; 
   mag.getEvent(&event);
  

   // Calculate the angle of the vector y,x from magnetic North
   float heading = (atan2(event.magnetic.y,event.magnetic.x) * 180) / Pi;

   // Normalize to 0-360 for a compass heading
   if (heading < 0)
   {
      heading = 360 + heading;
   }

   // Now read the accelerometer to control the motion.
   accel.getEvent(&event);
    x=event.acceleration.x;
   y=event.acceleration.y;
    z=event.acceleration.z;
   f= sqrt(x*x+y*y+z*z);

   Serial.print("f: "); Serial.print (f); Serial.print("  ");
  Serial.print("Y: "); Serial.print(f); Serial.print("  ");
  Serial.print("Z: "); Serial.print(f); Serial.print("  ");Serial.println("m/s^2 ");
  delay(0);

   // Check for mode change commands


   // apply a little frictional damping to keep things in control and prevent perpetual motion
   MomentumH *= friction;
   MomentumV *= friction;

   // Calculate the horizontal and vertical effect on the virtual pendulum
   // 'pos' is a pixel address, so we multiply by 'increment' to get radians.
   float TorqueH = cos(pos * increment);  // peaks at top and bottom of the swing
   float TorqueV = sin(pos * incrementB);    // peaks when the pendulum is horizontal

   // Add the incremental acceleration to the existing momentum
   // This code assumes that the accelerometer is mounted upside-down, level
   // and with the X-axis pointed forward.  So the Y axis reads the horizontal
   // acceleration and the inverse of the Z axis is gravity.
   // For other orientations of the sensor, just change the axis to match.
   MomentumH += TorqueH * event.acceleration.y / swing;
   if (antiGravity)
   {
     MomentumV += TorqueV * event.acceleration.z / gravity;
   }
   else
   {
     MomentumV -= TorqueV * event.acceleration.z / gravity;
   }

   // Calculate the new position
   pos += MomentumH + MomentumV;
   
   // handle the wrap-arounds at the top
   while (round(pos) < 0) pos += 39.0;
   while (round(pos) > 38) pos -= 39.0;

   // Now re-compute the display
   for (int i = 0; i < 39; i++)
   {
      // Compute the distance bewteen the pixel and the center
      // point of the virtual pendulum.
      float diff = i - pos;

      // Light up nearby pixels proportional to their proximity to 'pos'
      if (fabs(diff) <= halfWidth) 
      {
         uint32_t color;
         float proximity = halfWidth - fabs(diff) * 200;

         // pick a color based on heading & proximity to 'pos'
         color = selectColor(heading, proximity);
         
         // do both eyes
         strip.setPixelColor(i, color);
         if (mirroredEyes)
         {
           strip.setPixelColor(38 - i, color);
         }
         else
         {
           strip.setPixelColor(38 - i, color);
         }
      }
      else // all others are off
      {
         strip.setPixelColor(i, 0);
         if (mirroredEyes)
         {
           strip.setPixelColor(38 - i, 0);
         }
         else
         {
           strip.setPixelColor(38 - i, 0);
         }
      }
   }
   // Now show it!
   strip.show();
}

   

// choose a color based on the compass heading and proximity to "pos".
uint32_t selectColor(float heading, float proximity)
{
     uint32_t color;

     // Choose eye color based on the compass heading
     if (heading < 30)
     {
        color = strip.Color(255, 0, 0);
     }
     else if (heading < 60)
     {
        color = strip.Color(0, 255, 255);
     }
     else if (heading < 90)
     {
        color = strip.Color(127, 0, 255);
     }
     else if (heading < 120)
     {
        color = strip.Color(128, 255, 0);
     }
     else if (heading < 150)
     {
        color = strip.Color(255, 0, 128);
     }
     else if (heading < 180)
     {
        color = strip.Color(0, 255, 64);
     }
     else if (heading < 210)
     {
        color = strip.Color(0, 21, 255);
     }
     else if (heading < 240)
     {
        color = strip.Color(255, 191, 0);
     }
     else if (heading < 270)
     {
        color = strip.Color(255, 0, 0);
     }
     else if (heading < 300)
     {
        color = strip.Color(0, 255, 255);
     }
     else if (heading < 330)
     {
        color = strip.Color(127, 0, 255);
     }
     else // 300-360
     {
        color = strip.Color(128, 255, 0);
     }
}

// monitor orientation for mode-change 'gestures'
void pattern(sensors_event_t event)
 
{
accel.getEvent(&event);
    x=event.acceleration.x;
   y=event.acceleration.y;
    z=event.acceleration.z;
   f= sqrt(x*x+y*y+z*z);

if (f > 25)

   int p = random(2);  // choose one of 5 random patterns
   switch (p)
   {
       case 1:
           spin(strip.Color(255,0,0), 1, 500);
           break;
       case 2:
           spin(strip.Color(0,0,255), 1, 500);
           break;
       
           
   }
}

// Reset to default
void resetModes()
{
 
   
   /// spin-up
   spin(strip.Color(255,0,0), 1, 500);
   spin(strip.Color(0,255,0), 1, 500);
   spin(strip.Color(0,0,255), 1, 500);
   spinUp();
}

// gradual spin up

void spinUp()
{
  
   for (int i = 300; i > 0;  i -= 20)
   {
     spin(strip.Color(255,0,0), 1, i);
   }
   pos = 0;
   // leave it with some momentum and let it 'coast' to a stop
   MomentumH = 3;  
}
void spinUpB()
{
   for (int i = 150; i > 0;  i -= 20)
   {
     spin(strip.Color(0,255,0), 1, i);
   }
   pos = 0;
   // leave it with some momentum and let it 'coast' to a stop
   MomentumH = 3;  
}

// Gradual spin down
void spinDown()
{
   for (int i = 1; i < 30; i++)
   {
     spin(strip.Color(255,0,0), 1, i += 20);
   }
   // Stop it dead at the top and let it swing to the bottom on its own
   pos = 0;
   MomentumH = MomentumV = 0;
}
void spinDownB()
{
   for (int i = 1; i < 30; i++)
   {
     spin(strip.Color(0,0,255), 1, i += 20);
   }
   // Stop it dead at the top and let it swing to the bottom on its own
   pos = 0;
   MomentumH = MomentumV = 0;
}



// utility function for feedback on mode changes.
void spin(uint32_t color, int count, int time)
{
  for (int j = 0; j < count; j++)
  {
    for (int i = 0; i < 39; i++)
    {
      strip.setPixelColor(i, color);
      strip.setPixelColor(38 - i, color);
      strip.show();
      delay(max(time / 39, 1));
      strip.setPixelColor(i, 0);
      strip.setPixelColor(38 - i, 0);
      strip.show();
    }
  }
}
Last edited by adafruit_support_bill on Sun Sep 21, 2014 8:02 am, edited 1 time in total.
Reason: please use the </> button when submitting code. press </>, then paste your code between the [code] [/code] tags.

User avatar
adafruit_support_bill
 
Posts: 88086
Joined: Sat Feb 07, 2009 10:11 am

Re: Code for LSM303

Post by adafruit_support_bill »

I've tried the following code but its not working.
Can you be more specific? What are the symptoms?
Also, when posting code to the forums, please use

Code: Select all

 tags.  Press the button labeled </> and paste your code between the tags.

User avatar
niknak35
 
Posts: 53
Joined: Sat Apr 26, 2014 10:59 pm

Re: Code for LSM303

Post by niknak35 »

The if case thing looks perfect but fails to trigger any animations. Perhaps i'm missing some syntax or its in the wrong spt
Thanks
Nick

Code: Select all

// Googly Eye Goggles
// By Bill Earl
// For Adafruit Industries
//
// The googly eye effect is based on a physical model of a pendulum.
// The pendulum motion is driven by accelerations in 2 axis.
// Eye color varies with orientation of the magnetometer

#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_LSM303_U.h>
#include <Adafruit_NeoPixel.h>

#define PIN 6

// We could do this as 2 16-pixel rings wired in parallel.
// But keeping them separate lets us do the right and left
// eyes separately if we want.

Adafruit_NeoPixel strip = Adafruit_NeoPixel(39, PIN, NEO_GRB + NEO_KHZ800);
int x; 
int y; 
int z;
int f;
int p;

Adafruit_LSM303_Accel_Unified accel = Adafruit_LSM303_Accel_Unified(54321);
Adafruit_LSM303_Mag_Unified mag = Adafruit_LSM303_Mag_Unified(12345);
 
float pos = 0;  // Starting center position of pupil
float posB = 0;  // Starting center position of pupil
float increment = 2 * 3.14159 / 16; // distance between pixels in radians
float incrementB = 2 * 3.14159 / 16; // distance between pixels in radians
float MomentumH = 0; // horizontal component of pupil rotational inertia
float MomentumV = 0; // vertical component of pupil rotational inertia

// Tuning constants. (a.k.a. "Fudge Factors)  
// These can be tweaked to adjust the liveliness and sensitivity of the eyes.
const float friction = 0.95; // frictional damping constant.  1.0 is no friction.
const float swing = 60;  // arbitrary divisor for gravitational force
const float gravity = 200;  // arbitrary divisor for lateral acceleration
const float nod = 7.5; // accelerometer threshold for toggling modes

long nodStart = 0;
long nodTime = 2000;

bool antiGravity = false;  // The pendulum will anti-gravitate to the top.
bool mirroredEyes = false; // The left eye will mirror the right.

const float halfWidth = 1.25; // half-width of pupil (in pixels)

// Pi for calculations - not the raspberry type
const float Pi = 3.14159;

void setup(void) 
{
  Serial.begin(9600); 
  strip.begin();
   strip.show(); // Initialize all pixels to 'off'  sensor_t sensor;

   // Initialize the sensors
   accel.begin();
   mag.begin();
   
   resetModes();
}

// main processing loop
void loop(void) 
{
   // Read the magnetometer and determine the compass heading:
   sensors_event_t event; 
   mag.getEvent(&event);
  

   // Calculate the angle of the vector y,x from magnetic North
   float heading = (atan2(event.magnetic.y,event.magnetic.x) * 180) / Pi;

   // Normalize to 0-360 for a compass heading
   if (heading < 0)
   {
      heading = 360 + heading;
   }

   // Now read the accelerometer to control the motion.
   accel.getEvent(&event);
    x=event.acceleration.x;
   y=event.acceleration.y;
    z=event.acceleration.z;
   f= sqrt(x*x+y*y+z*z);

   Serial.print("f: "); Serial.print (f); Serial.print("  ");
  Serial.print("Y: "); Serial.print(f); Serial.print("  ");
  Serial.print("Z: "); Serial.print(f); Serial.print("  ");Serial.println("m/s^2 ");
  delay(0);

   // Check for mode change commands


   // apply a little frictional damping to keep things in control and prevent perpetual motion
   MomentumH *= friction;
   MomentumV *= friction;

   // Calculate the horizontal and vertical effect on the virtual pendulum
   // 'pos' is a pixel address, so we multiply by 'increment' to get radians.
   float TorqueH = cos(pos * increment);  // peaks at top and bottom of the swing
   float TorqueV = sin(pos * incrementB);    // peaks when the pendulum is horizontal

   // Add the incremental acceleration to the existing momentum
   // This code assumes that the accelerometer is mounted upside-down, level
   // and with the X-axis pointed forward.  So the Y axis reads the horizontal
   // acceleration and the inverse of the Z axis is gravity.
   // For other orientations of the sensor, just change the axis to match.
   MomentumH += TorqueH * event.acceleration.y / swing;
   if (antiGravity)
   {
     MomentumV += TorqueV * event.acceleration.z / gravity;
   }
   else
   {
     MomentumV -= TorqueV * event.acceleration.z / gravity;
   }

   // Calculate the new position
   pos += MomentumH + MomentumV;
   
   // handle the wrap-arounds at the top
   while (round(pos) < 0) pos += 39.0;
   while (round(pos) > 38) pos -= 39.0;

   // Now re-compute the display
   for (int i = 0; i < 39; i++)
   {
      // Compute the distance bewteen the pixel and the center
      // point of the virtual pendulum.
      float diff = i - pos;

      // Light up nearby pixels proportional to their proximity to 'pos'
      if (fabs(diff) <= halfWidth) 
      {
         uint32_t color;
         float proximity = halfWidth - fabs(diff) * 200;

         // pick a color based on heading & proximity to 'pos'
         color = selectColor(heading, proximity);
         
         // do both eyes
         strip.setPixelColor(i, color);
         if (mirroredEyes)
         {
           strip.setPixelColor(38 - i, color);
         }
         else
         {
           strip.setPixelColor(38 - i, color);
         }
      }
      else // all others are off
      {
         strip.setPixelColor(i, 0);
         if (mirroredEyes)
         {
           strip.setPixelColor(38 - i, 0);
         }
         else
         {
           strip.setPixelColor(38 - i, 0);
         }
      }
   }
   // Now show it!
   strip.show();
}

   

// choose a color based on the compass heading and proximity to "pos".
uint32_t selectColor(float heading, float proximity)
{
     uint32_t color;

     // Choose eye color based on the compass heading
     if (heading < 30)
     {
        color = strip.Color(255, 0, 0);
     }
     else if (heading < 60)
     {
        color = strip.Color(0, 255, 255);
     }
     else if (heading < 90)
     {
        color = strip.Color(127, 0, 255);
     }
     else if (heading < 120)
     {
        color = strip.Color(128, 255, 0);
     }
     else if (heading < 150)
     {
        color = strip.Color(255, 0, 128);
     }
     else if (heading < 180)
     {
        color = strip.Color(0, 255, 64);
     }
     else if (heading < 210)
     {
        color = strip.Color(0, 21, 255);
     }
     else if (heading < 240)
     {
        color = strip.Color(255, 191, 0);
     }
     else if (heading < 270)
     {
        color = strip.Color(255, 0, 0);
     }
     else if (heading < 300)
     {
        color = strip.Color(0, 255, 255);
     }
     else if (heading < 330)
     {
        color = strip.Color(127, 0, 255);
     }
     else // 300-360
     {
        color = strip.Color(128, 255, 0);
     }
}

// monitor orientation for mode-change 'gestures'
void pattern(sensors_event_t event)
 
{
accel.getEvent(&event);
    x=event.acceleration.x;
   y=event.acceleration.y;
    z=event.acceleration.z;
   f= sqrt(x*x+y*y+z*z);

if (f > 25)

   int p = random(2);  // choose one of 5 random patterns
   switch (p)
   {
       case 1:
           spin(strip.Color(255,0,0), 1, 500);
           break;
       case 2:
           spin(strip.Color(0,0,255), 1, 500);
           break;
       
           
   }
}

// Reset to default
void resetModes()
{
 
   
   /// spin-up
   spin(strip.Color(255,0,0), 1, 500);
   spin(strip.Color(0,255,0), 1, 500);
   spin(strip.Color(0,0,255), 1, 500);
   spinUp();
}

// gradual spin up

void spinUp()
{
  
   for (int i = 300; i > 0;  i -= 20)
   {
     spin(strip.Color(255,0,0), 1, i);
   }
   pos = 0;
   // leave it with some momentum and let it 'coast' to a stop
   MomentumH = 3;  
}
void spinUpB()
{
   for (int i = 150; i > 0;  i -= 20)
   {
     spin(strip.Color(0,255,0), 1, i);
   }
   pos = 0;
   // leave it with some momentum and let it 'coast' to a stop
   MomentumH = 3;  
}

// Gradual spin down
void spinDown()
{
   for (int i = 1; i < 30; i++)
   {
     spin(strip.Color(255,0,0), 1, i += 20);
   }
   // Stop it dead at the top and let it swing to the bottom on its own
   pos = 0;
   MomentumH = MomentumV = 0;
}
void spinDownB()
{
   for (int i = 1; i < 30; i++)
   {
     spin(strip.Color(0,0,255), 1, i += 20);
   }
   // Stop it dead at the top and let it swing to the bottom on its own
   pos = 0;
   MomentumH = MomentumV = 0;
}



// utility function for feedback on mode changes.
void spin(uint32_t color, int count, int time)
{
  for (int j = 0; j < count; j++)
  {
    for (int i = 0; i < 39; i++)
    {
      strip.setPixelColor(i, color);
      strip.setPixelColor(38 - i, color);
      strip.show();
      delay(max(time / 39, 1));
      strip.setPixelColor(i, 0);
      strip.setPixelColor(38 - i, 0);
      strip.show();
    }
  }
}   
Last edited by adafruit_support_bill on Sun Sep 21, 2014 8:12 pm, edited 1 time in total.
Reason: Fixed [code] tags

User avatar
adafruit_support_bill
 
Posts: 88086
Joined: Sat Feb 07, 2009 10:11 am

Re: Code for LSM303

Post by adafruit_support_bill »

Please use

Code: Select all

[/b] tags, not [b][quote] [/b]tags.  In addition to not cluttering up the thread with long listings, it preserves the formatting and makes it easier for us to copy the code into a proper code editor and test things.

Also, please describe the exact symptoms of the problem.  Saying "it doesn't work" doesn't give us much to work with.

User avatar
niknak35
 
Posts: 53
Joined: Sat Apr 26, 2014 10:59 pm

Re: Code for LSM303

Post by niknak35 »

Ok the "if case" code doesn't trigger animations listed in the cases. ie no animations are triggered when the f>25

Code: Select all

// Googly Eye Goggles
// By Bill Earl
// For Adafruit Industries
//
// The googly eye effect is based on a physical model of a pendulum.
// The pendulum motion is driven by accelerations in 2 axis.
// Eye color varies with orientation of the magnetometer

#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_LSM303_U.h>
#include <Adafruit_NeoPixel.h>

#define PIN 6

// We could do this as 2 16-pixel rings wired in parallel.
// But keeping them separate lets us do the right and left
// eyes separately if we want.

Adafruit_NeoPixel strip = Adafruit_NeoPixel(39, PIN, NEO_GRB + NEO_KHZ800);
int x; 
int y; 
int z;
int f;
int p;

Adafruit_LSM303_Accel_Unified accel = Adafruit_LSM303_Accel_Unified(54321);
Adafruit_LSM303_Mag_Unified mag = Adafruit_LSM303_Mag_Unified(12345);
 
float pos = 0;  // Starting center position of pupil
float posB = 0;  // Starting center position of pupil
float increment = 2 * 3.14159 / 16; // distance between pixels in radians
float incrementB = 2 * 3.14159 / 16; // distance between pixels in radians
float MomentumH = 0; // horizontal component of pupil rotational inertia
float MomentumV = 0; // vertical component of pupil rotational inertia

// Tuning constants. (a.k.a. "Fudge Factors)  
// These can be tweaked to adjust the liveliness and sensitivity of the eyes.
const float friction = 0.95; // frictional damping constant.  1.0 is no friction.
const float swing = 60;  // arbitrary divisor for gravitational force
const float gravity = 200;  // arbitrary divisor for lateral acceleration
const float nod = 7.5; // accelerometer threshold for toggling modes

long nodStart = 0;
long nodTime = 2000;

bool antiGravity = false;  // The pendulum will anti-gravitate to the top.
bool mirroredEyes = false; // The left eye will mirror the right.

const float halfWidth = 1.25; // half-width of pupil (in pixels)

// Pi for calculations - not the raspberry type
const float Pi = 3.14159;

void setup(void) 
{
  Serial.begin(9600); 
  strip.begin();
   strip.show(); // Initialize all pixels to 'off'  sensor_t sensor;

   // Initialize the sensors
   accel.begin();
   mag.begin();
   
   resetModes();
}

// main processing loop
void loop(void) 
{
   // Read the magnetometer and determine the compass heading:
   sensors_event_t event; 
   mag.getEvent(&event);
  

   // Calculate the angle of the vector y,x from magnetic North
   float heading = (atan2(event.magnetic.y,event.magnetic.x) * 180) / Pi;

   // Normalize to 0-360 for a compass heading
   if (heading < 0)
   {
      heading = 360 + heading;
   }

   // Now read the accelerometer to control the motion.
   accel.getEvent(&event);
    x=event.acceleration.x;
   y=event.acceleration.y;
    z=event.acceleration.z;
   f= sqrt(x*x+y*y+z*z);

   Serial.print("f: "); Serial.print (f); Serial.print("  ");
  Serial.print("Y: "); Serial.print(f); Serial.print("  ");
  Serial.print("Z: "); Serial.print(f); Serial.print("  ");Serial.println("m/s^2 ");
  delay(0);

   // Check for mode change commands


   // apply a little frictional damping to keep things in control and prevent perpetual motion
   MomentumH *= friction;
   MomentumV *= friction;

   // Calculate the horizontal and vertical effect on the virtual pendulum
   // 'pos' is a pixel address, so we multiply by 'increment' to get radians.
   float TorqueH = cos(pos * increment);  // peaks at top and bottom of the swing
   float TorqueV = sin(pos * incrementB);    // peaks when the pendulum is horizontal

   // Add the incremental acceleration to the existing momentum
   // This code assumes that the accelerometer is mounted upside-down, level
   // and with the X-axis pointed forward.  So the Y axis reads the horizontal
   // acceleration and the inverse of the Z axis is gravity.
   // For other orientations of the sensor, just change the axis to match.
   MomentumH += TorqueH * event.acceleration.y / swing;
   if (antiGravity)
   {
     MomentumV += TorqueV * event.acceleration.z / gravity;
   }
   else
   {
     MomentumV -= TorqueV * event.acceleration.z / gravity;
   }

   // Calculate the new position
   pos += MomentumH + MomentumV;
   
   // handle the wrap-arounds at the top
   while (round(pos) < 0) pos += 39.0;
   while (round(pos) > 38) pos -= 39.0;

   // Now re-compute the display
   for (int i = 0; i < 39; i++)
   {
      // Compute the distance bewteen the pixel and the center
      // point of the virtual pendulum.
      float diff = i - pos;

      // Light up nearby pixels proportional to their proximity to 'pos'
      if (fabs(diff) <= halfWidth) 
      {
         uint32_t color;
         float proximity = halfWidth - fabs(diff) * 200;

         // pick a color based on heading & proximity to 'pos'
         color = selectColor(heading, proximity);
         
         // do both eyes
         strip.setPixelColor(i, color);
         if (mirroredEyes)
         {
           strip.setPixelColor(38 - i, color);
         }
         else
         {
           strip.setPixelColor(38 - i, color);
         }
      }
      else // all others are off
      {
         strip.setPixelColor(i, 0);
         if (mirroredEyes)
         {
           strip.setPixelColor(38 - i, 0);
         }
         else
         {
           strip.setPixelColor(38 - i, 0);
         }
      }
   }
   // Now show it!
   strip.show();
}

   

// choose a color based on the compass heading and proximity to "pos".
uint32_t selectColor(float heading, float proximity)
{
     uint32_t color;

     // Choose eye color based on the compass heading
     if (heading < 30)
     {
        color = strip.Color(255, 0, 0);
     }
     else if (heading < 60)
     {
        color = strip.Color(0, 255, 255);
     }
     else if (heading < 90)
     {
        color = strip.Color(127, 0, 255);
     }
     else if (heading < 120)
     {
        color = strip.Color(128, 255, 0);
     }
     else if (heading < 150)
     {
        color = strip.Color(255, 0, 128);
     }
     else if (heading < 180)
     {
        color = strip.Color(0, 255, 64);
     }
     else if (heading < 210)
     {
        color = strip.Color(0, 21, 255);
     }
     else if (heading < 240)
     {
        color = strip.Color(255, 191, 0);
     }
     else if (heading < 270)
     {
        color = strip.Color(255, 0, 0);
     }
     else if (heading < 300)
     {
        color = strip.Color(0, 255, 255);
     }
     else if (heading < 330)
     {
        color = strip.Color(127, 0, 255);
     }
     else // 300-360
     {
        color = strip.Color(128, 255, 0);
     }
}

// monitor orientation for mode-change 'gestures'
void pattern(sensors_event_t event)
 
{
accel.getEvent(&event);
    x=event.acceleration.x;
   y=event.acceleration.y;
    z=event.acceleration.z;
   f= sqrt(x*x+y*y+z*z);

if (f > 25)

   int p = random(2);  // choose one of 5 random patterns
   switch (p)
   {
       case 1:
           spin(strip.Color(255,0,0), 1, 500);
           break;
       case 2:
           spin(strip.Color(0,0,255), 1, 500);
           break;
       
           
   }
}

// Reset to default
void resetModes()
{
 
   
   /// spin-up
   spin(strip.Color(255,0,0), 1, 500);
   spin(strip.Color(0,255,0), 1, 500);
   spin(strip.Color(0,0,255), 1, 500);
   spinUp();
}

// gradual spin up

void spinUp()
{
  
   for (int i = 300; i > 0;  i -= 20)
   {
     spin(strip.Color(255,0,0), 1, i);
   }
   pos = 0;
   // leave it with some momentum and let it 'coast' to a stop
   MomentumH = 3;  
}
void spinUpB()
{
   for (int i = 150; i > 0;  i -= 20)
   {
     spin(strip.Color(0,255,0), 1, i);
   }
   pos = 0;
   // leave it with some momentum and let it 'coast' to a stop
   MomentumH = 3;  
}

// Gradual spin down
void spinDown()
{
   for (int i = 1; i < 30; i++)
   {
     spin(strip.Color(255,0,0), 1, i += 20);
   }
   // Stop it dead at the top and let it swing to the bottom on its own
   pos = 0;
   MomentumH = MomentumV = 0;
}
void spinDownB()
{
   for (int i = 1; i < 30; i++)
   {
     spin(strip.Color(0,0,255), 1, i += 20);
   }
   // Stop it dead at the top and let it swing to the bottom on its own
   pos = 0;
   MomentumH = MomentumV = 0;
}



// utility function for feedback on mode changes.
void spin(uint32_t color, int count, int time)
{
  for (int j = 0; j < count; j++)
  {
    for (int i = 0; i < 39; i++)
    {
      strip.setPixelColor(i, color);
      strip.setPixelColor(38 - i, color);
      strip.show();
      delay(max(time / 39, 1));
      strip.setPixelColor(i, 0);
      strip.setPixelColor(38 - i, 0);
      strip.show();
    }
  }
}

Locked
Please be positive and constructive with your questions and comments.

Return to “Glowy things (LCD, LED, TFT, EL) purchased at Adafruit”