MagneticLight - Modified version based on ST Components

Dependencies:   PololuLedStrip X_NUCLEO_IKS01A1 mbed

main.cpp

Committer:
Arkadi
Date:
2017-02-07
Revision:
4:b44bc6256182
Parent:
3:8cbf1e2122d4

File content as of revision 4:b44bc6256182:

/*
    STM32 - Magnetic light - Updated version to work with ST components. (MCU ,  Magnetic sensor)
    Arkadiraf@gmail.com  - 07/02/2017
    
    Based on my previous arduino version published at:
*/

/*
 Hardware setup: STM32 - Nucleo-F432KC
 Led strip 74 leds ws2812b 60 leds / meter
 5V  -  5V
 D11 -  Led Din (through voltage converter 3v3->5V)
 GND -  GND

 Magnetic sensor LIS3MDL I2C : https://www.pololu.com/product/2737
 3V3 - Vin
 GND - GND
 D5  - SCL
 D4  - SDA 
 
*/

///////////////
// Libraries //
///////////////
#include "mbed.h"
#include "PololuLedStrip.h"
#include "x_nucleo_iks01a1.h"
//////////////
// Defines: //
//////////////
#define DEBBUG_MSG1
#define LED_COUNT 74
#define blackColor {0,0,0}
#define SAMPLEDELAY 30 // roughly 30 hz // magnetic sensor sample rate / Led update
////////////////////
// define Objects //
////////////////////
PololuLedStrip ledStrip(D11);
Timer timer;
Serial pc(SERIAL_TX, SERIAL_RX,57600);

// Magnetic sensor:
/* Instantiate the expansion board */
static X_NUCLEO_IKS01A1 *mems_expansion_board = X_NUCLEO_IKS01A1::Instance(D4, D5);
static MagneticSensor *magnetometer = mems_expansion_board->magnetometer;

///////////////
// variables //
///////////////

// LED variables:
rgb_color colors[LED_COUNT];
rgb_color setColor= {0,0,0};

// define array of pixel vectors based on the compas:
float Pixel_Vect_Float[3]= {0,0,0}; // variable to store LED Power
const int Pixel_Vect[LED_COUNT][3]= {
    {  -41,  -86,  -31 },
    {  -54,  -71,  -45 },
    {  -66,  -47,  -58 },
    {  -75,  -18,  -63 },
    {  -76,  17,  -63 },
    {  -68,  44,  -58 },
    {  -56,  67,  -48 },
    {  -41,  86,  -32 },
    {  -35,  94,  -2 },
    {  -61,  79,  -4 },
    {  -82,  57,  -4 },
    {  -99,  10,  -10 },
    {  -97,  -20,  -6 },
    {  -87,  -47,  -6 },
    {  -68,  -72,  -7 },
    {  -24,  -97,  -3 },
    {  -50,  -81,  30 },
    {  -66,  -63,  41 },
    {  -80,  -37,  49 },
    {  -85,  0,  53 },
    {  -80,  32,  51 },
    {  -71,  56,  42 },
    {  -50,  79,  33 },
    {  -30,  94,  19 },
    {  -20,  94,  29 },
    {  -25,  81,  54 },
    {  -34,  54,  78 },
    {  -36,  24,  90 },
    {  -36,  -15,  92 },
    {  -34,  -48,  81 },
    {  -25,  -69,  68 },
    {  -23,  -83,  54 },
    {  22,  -86,  46 },
    {  35,  -72,  60 },
    {  44,  -38,  80 },
    {  53,  -8,  86 },
    {  45,  31,  83 },
    {  35,  62,  70 },
    {  24,  84,  50 },
    {  10,  96,  24 },
    {  42,  91,  12 },
    {  68,  71,  19 },
    {  85,  44,  24 },
    {  95,  8,  28 },
    {  91,  -32,  28 },
    {  80,  -55,  25 },
    {  62,  -75,  20 },
    {  50,  -84,  21 },
    {  48,  -86,  -19 },
    {  67,  -70,  -25 },
    {  83,  -51,  -26 },
    {  93,  -21,  -31 },
    {  94,  13,  -30 },
    {  85,  43,  -29 },
    {  67,  70,  -25 },
    {  42,  90,  -16 },
    {  19,  91,  -35 },
    {  38,  72,  -58 },
    {  48,  45,  -74 },
    {  55,  20,  -81 },
    {  55,  -20,  -81 },
    {  47,  -54,  -70 },
    {  31,  -76,  -56 },
    {  20,  -87,  -43 },
    {  -10,  -88,  -45 },
    {  -14,  -73,  -67 },
    {  -13,  -50,  -85 },
    {  -17,  -14,  -98 },
    {  -12,  17,  -98 },
    {  -14,  50,  -86 },
    {  -13,  72,  -68 },
    {  -9,  89,  -47 },
    {  -12,  99,  -10 },
    {  -12,  99,  -10 }
};



// Magnetic sensor:
int16_t axesRaw[3]; // raw data from magnetic sensor
float Mag_raw[3]= {1,0,0}; //Magnetometer
float Mag[3]= {0,0,0};     //Magnetometer
float Mag_Bias[3]= {0,0,0};     //Magnetometer bias values

float MagOut[3]= {0,0,0}; //Magnetometer
float LMagOut[3]= {0,0,0}; //Last Magnetometer reading
float MagIn[3]= {0,0,0}; //Magnetometer
float LMagIn[3]= {0,0,0}; //Last Magnetometer reading
float AHPF=0.99;

float Mag_Norm[3]= {0,0,0}; //Magnetometer normalized
float Mag_ABS=1; // Vector size indication how far the magnet is
float CosAngle=0; // cosin of the angle between the two vectors
float LedPower=0; // variable to store LED Power
uint8_t LedPower_Byte=0; // Byte varible to set led power

// timer variables
int sampleMillis=0;
int timeMillis=0;

///////////////
// Functions //
///////////////
// HPF filter:
void HighPassFilter();
// Update Pixel array based on mag sensor
void Update_Pixels_Mag();
// move dot throught the strip
void dotMove(rgb_color dotColor);
// update strip colors
void colorStrip();

////////////////////////
//  Main Code Setup : //
////////////////////////
int main()
{
    // init timer
    timer.start();

    // init magnetometer - Rewrite library or add options to change magnetic full scale and sample rate
    // read magnetic sensor ID
    uint8_t id;
    magnetometer->ReadID(&id);
    pc.printf("LIS3MDL magnetometer              = 0x%X\r\n", id);

    ///////////////////////
    //  Main Code Loop : //
    ///////////////////////
    while(1) {
        timeMillis=timer.read_ms();
        // check timer overflow // returnes int.
        if (timeMillis<0) {
            timer.reset();
            timeMillis=timer.read_ms();
            // reset variables
            sampleMillis=0;
        }

        // update leds based on magnetometer
        if (timeMillis-sampleMillis>SAMPLEDELAY) {
            sampleMillis=timeMillis;

            // Read magnetometer values
            magnetometer->Get_M_AxesRaw(axesRaw);
            // debbug messages
            //pc.printf("LIS3MDL [mag/mgauss]:  %6ld, %6ld, %6ld\r\n", axesRaw[0], axesRaw[1], axesRaw[2]);
            
            // update float ariables
            // axis adjustment to fit the previous setup, (visual aligment).
            Mag_raw[0]=-axesRaw[1];
            Mag_raw[1]=axesRaw[0];
            Mag_raw[2]=-axesRaw[2];

            // bias samples and scale
            Mag[0]=Mag_raw[0]-Mag_Bias[0];
            Mag[1]=Mag_raw[1]-Mag_Bias[1];
            Mag[2]=Mag_raw[2]-Mag_Bias[2];

            Mag_ABS=sqrt(Mag[0]*Mag[0]+Mag[1]*Mag[1]+Mag[2]*Mag[2]);
            Mag_Norm[0]=Mag[0]/Mag_ABS;
            Mag_Norm[1]=Mag[1]/Mag_ABS;
            Mag_Norm[2]=Mag[2]/Mag_ABS;

            // HPF filter:
            HighPassFilter();

            // Update Pixel array based on mag sensor
            Update_Pixels_Mag();
            
            // Send the colors to the LED strip.
            ledStrip.write(colors, LED_COUNT);

            // debug messages:
            //pc.printf("DBG_1: mill: %d , MAG: %.2f , %.2f , %.2f \r\n",sampleMillis,Mag[0],Mag[1],Mag[2]);
            //pc.printf("DBG_1: mill: %d , MAG: %.2f , %.2f , %.2f \r\n",sampleMillis,Mag_Norm[0],Mag_Norm[1],Mag_Norm[2]);
        }// end update pixels based on mag



        // pixels test
        if (0) {
            setColor=(rgb_color) {
                125,125,0
            };
            dotMove(setColor);

            // Send the colors to the LED strip.
            ledStrip.write(colors, LED_COUNT);
            wait_ms(10);
        }
    }// end main loop
}// end main

///////////////
// Functions //
///////////////
// HPF filter:
void HighPassFilter()
{
    LMagIn[0]=MagIn[0];
    LMagIn[1]=MagIn[1];
    LMagIn[2]=MagIn[2];
    LMagOut[0]=MagOut[0];
    LMagOut[1]=MagOut[1];
    LMagOut[2]=MagOut[2];
    // update reading
    MagIn[0]=Mag_raw[0];
    MagIn[1]=Mag_raw[1];
    MagIn[2]=Mag_raw[2];
    // update filter
    MagOut[0]=AHPF*(LMagOut[0]+MagIn[0]-LMagIn[0]);
    MagOut[1]=AHPF*(LMagOut[1]+MagIn[1]-LMagIn[1]);
    MagOut[2]=AHPF*(LMagOut[2]+MagIn[2]-LMagIn[2]);

    // Normalize vector and calculate ABS value
    Mag_ABS=sqrt(MagOut[0]*MagOut[0]+MagOut[1]*MagOut[1]+MagOut[2]*MagOut[2]);
    Mag_Norm[0]=MagOut[0]/Mag_ABS;
    Mag_Norm[1]=MagOut[1]/Mag_ABS;
    Mag_Norm[2]=MagOut[2]/Mag_ABS;
}// end high pass filter

// Update Pixel array based on mag sensor
void Update_Pixels_Mag()
{
    // Calculate angle between magnetic vector and LED vectors
    for (uint16_t ii=0 ; ii<LED_COUNT ; ii++) {
        Pixel_Vect_Float[0]=((float)Pixel_Vect[ii][0])/100;
        Pixel_Vect_Float[1]=((float)Pixel_Vect[ii][1])/100;
        Pixel_Vect_Float[2]=((float)Pixel_Vect[ii][2])/100;
        CosAngle=Mag_Norm[0]*Pixel_Vect_Float[0] + Mag_Norm[1]*Pixel_Vect_Float[1] + Mag_Norm[2]*Pixel_Vect_Float[2];
        //LedPower=Mag_ABS*CosAngle*CosAngle*CosAngle*CosAngle*CosAngle;
        LedPower=Mag_ABS*((float)pow(CosAngle,9));
        if (LedPower>=0) {
            if (LedPower>255) LedPower=255;
            LedPower_Byte=(uint8_t)(LedPower);
            colors[ii] = (rgb_color) {
                LedPower_Byte, 0, 0
            };
        }
        if (LedPower<0) {
            if (LedPower<-255) LedPower=-255;
            LedPower_Byte=(uint8_t)(-LedPower);
            colors[ii] = (rgb_color) {
                0, 0, LedPower_Byte
            };
        }
    }
}// end pixel update based on magnetic field


// move dot throught the strip
void dotMove(rgb_color dotColor)
{
    static int pixelNum=0;
    colors[pixelNum]=dotColor;
    if (pixelNum==0) {
        colors[LED_COUNT-1]=(rgb_color) blackColor;
    } else {
        colors[pixelNum-1]=(rgb_color) blackColor;
    }
    pixelNum++;
    pixelNum=pixelNum%LED_COUNT;
}

// update strip colors
void colorStrip()
{
    // Update the colors array.
    uint8_t time = timer.read_ms() >> 3;
    for(uint32_t i = 0; i < LED_COUNT; i++) {
        uint8_t x = (time - 8*i)%255;
        colors[i] = (rgb_color) {
            x, 255 - x, x
        };
    }
}