
configure sensors on FRDM KL46Z and send data through Serial port. Need host(PC) software to interact with. Sampling rate can vary by proper instruction
Dependencies: EventFramework mbed
Revision 0:2b49a387e831, committed 2014-02-15
- Comitter:
- xmnan
- Date:
- Sat Feb 15 07:52:46 2014 +0000
- Commit message:
- original version.; Utilize EventFrameWork; sensors: MMA8451Q MAG3110 TSISensor lightSensor + analog input
Changed in this revision
diff -r 000000000000 -r 2b49a387e831 EventFramework.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/EventFramework.lib Sat Feb 15 07:52:46 2014 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/raulMrello/code/EventFramework/#ec12f2e32faf
diff -r 000000000000 -r 2b49a387e831 MAG3110.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MAG3110.cpp Sat Feb 15 07:52:46 2014 +0000 @@ -0,0 +1,140 @@ + +#include "MAG3110.h" +#include "mbed.h" + +/****************************************************************************** + * Constructors + ******************************************************************************/ +MAG3110::MAG3110(PinName sda, PinName scl,float dateRate, int overSample): _i2c(sda, scl), + _i2c_address(0x0E<<1), _pc(NULL), _debug(false) +{ + Setdr(dateRate); + Setosr(overSample); + begin(); +} + +MAG3110::MAG3110(PinName sda, PinName scl): _i2c(sda, scl), + _i2c_address(0x0E<<1), _pc(NULL), _debug(false),dr(MAG_3110_SAMPLE80),osr(MAG_3110_OVERSAMPLE2) +{ + begin(); +} + +MAG3110::MAG3110(PinName sda, PinName scl, Serial *pc): _i2c(sda, scl), + _i2c_address(0x0E<<1), _pc(pc), _debug(true),dr(MAG_3110_SAMPLE80),osr(MAG_3110_OVERSAMPLE2) +{ + begin(); +} + +void MAG3110::begin() +{ + + char cmd[2]; + + cmd[0] = MAG_CTRL_REG2; + cmd[1] = 0x80; + _i2c.write(_i2c_address, cmd, 2); + + cmd[0] = MAG_CTRL_REG1; +// cmd[1] = MAG_3110_SAMPLE80+MAG_3110_OVERSAMPLE2+MAG_3110_ACTIVE; + cmd[1] = dr+osr+MAG_3110_ACTIVE; + _i2c.write(_i2c_address, cmd, 2); + + // No adjustment initially + _avgX = 0; + _avgY = 0; +} + +// Read a single byte form 8 bit register, return as int +int MAG3110::readReg(char regAddr) +{ + char cmd[1]; + + cmd[0] = regAddr; + _i2c.write(_i2c_address, cmd, 1); + + cmd[0] = 0x00; + _i2c.read(_i2c_address, cmd, 1); + return (int)( cmd[0]); +} + + +// read a register per, pass first reg value, reading 2 bytes increments register +// Reads MSB first then LSB +int MAG3110::readVal(char regAddr) +{ + char cmd[2]; + + cmd[0] = regAddr; + _i2c.write(_i2c_address, cmd, 1); + + cmd[0] = 0x00; + cmd[1] = 0x00; + _i2c.read(_i2c_address, cmd, 2); + return (int)( (cmd[1]|(cmd[0] << 8))); //concatenate the MSB and LSB +} + + +float MAG3110::getHeading() +{ + int xVal = readVal(MAG_OUT_X_MSB); + int yVal = readVal(MAG_OUT_Y_MSB); + return (atan2((double)(yVal - _avgY),(double)(xVal - _avgX)))*180/PI; +} + +void MAG3110::getValues(int *xVal, int *yVal, int *zVal) +{ + *xVal = readVal(MAG_OUT_X_MSB); + *yVal = readVal(MAG_OUT_Y_MSB); + *zVal = readVal(MAG_OUT_Z_MSB); +} + + +void MAG3110::setCalibration(int minX, int maxX, int minY, int maxY ) +{ + _avgX=(maxX+minX)/2; + _avgY=(maxY+minY)/2; +} + +void MAG3110::Setdr(float dateRate) +{ + if (dateRate==80) + dr=MAG_3110_SAMPLE80; + else if(dateRate==40) + dr=MAG_3110_SAMPLE40; + else if(dateRate==20) + dr=MAG_3110_SAMPLE20; + else if(dateRate==10) + dr=MAG_3110_SAMPLE10; + else if(dateRate==5) + dr=MAG_3110_SAMPLE5; + else if(dateRate==2.5) + dr=MAG_3110_SAMPLE2_5; + else if(dateRate==1.25) + dr=MAG_3110_SAMPLE1_25; + else if(dateRate==0.625) + dr=MAG_3110_SAMPLE0_625; + else + dr=MAG_3110_SAMPLE80; +} + +void MAG3110::Setosr(int overSample) +{ + switch(overSample) + { + case 16:osr=MAG_3110_OVERSAMPLE1;break; + case 32:osr=MAG_3110_OVERSAMPLE2;break; + case 64:osr=MAG_3110_OVERSAMPLE3;break; + case 128:osr=MAG_3110_OVERSAMPLE4;break; + default:osr=MAG_3110_OVERSAMPLE2;break; + } +} + +void MAG3110::Overwrite_dr_osr(float dateRate,int overSample) +{ + char cmd[2]; + Setdr(dateRate); + Setosr(overSample); + cmd[0] = MAG_CTRL_REG1; + cmd[1] = dr+osr+MAG_3110_ACTIVE; + _i2c.write(_i2c_address, cmd, 2); +}
diff -r 000000000000 -r 2b49a387e831 MAG3110.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MAG3110.h Sat Feb 15 07:52:46 2014 +0000 @@ -0,0 +1,151 @@ +/* + * MAG3110 Sensor Library for mbed + * TODO: Add proper header + */ + +#ifndef MAG3110_H +#define MAG3110_H + +#include "mbed.h" + +#define PI 3.14159265359 + +#define MAG_ADDR 0x1D + +// define registers +#define MAG_DR_STATUS 0x00 +#define MAG_OUT_X_MSB 0x01 +#define MAG_OUT_X_LSB 0x02 +#define MAG_OUT_Y_MSB 0x03 +#define MAG_OUT_Y_LSB 0x04 +#define MAG_OUT_Z_MSB 0x05 +#define MAG_OUT_Z_LSB 0x06 +#define MAG_WHO_AM_I 0x07 +#define MAG_SYSMOD 0x08 +#define MAG_OFF_X_MSB 0x09 +#define MAG_OFF_X_LSB 0x0A +#define MAG_OFF_Y_MSB 0x0B +#define MAG_OFF_Y_LSB 0x0C +#define MAG_OFF_Z_MSB 0x0D +#define MAG_OFF_Z_LSB 0x0E +#define MAG_DIE_TEMP 0x0F +#define MAG_CTRL_REG1 0x10 +#define MAG_CTRL_REG2 0x11 + +// what should WHO_AM_I return? +#define MAG_3110_WHO_AM_I_VALUE 0xC4 + + +// Fields in registers +// CTRL_REG1: dr2,dr1,dr0 os1,os0 fr tm ac + +// Sampling rate from 80Hz down to 0.625Hz +#define MAG_3110_SAMPLE80 0 +#define MAG_3110_SAMPLE40 0x20 +#define MAG_3110_SAMPLE20 0x40 +#define MAG_3110_SAMPLE10 0x60 +#define MAG_3110_SAMPLE5 0x80 +#define MAG_3110_SAMPLE2_5 0xA0 +#define MAG_3110_SAMPLE1_25 0xC0 +#define MAG_3110_SAMPLE0_625 0xE0 + +// How many samples to average (lowers data rate) +#define MAG_3110_OVERSAMPLE1 0 //16 +#define MAG_3110_OVERSAMPLE2 0x08 //32, sample rate decrease to half +#define MAG_3110_OVERSAMPLE3 0x10 //64, sample rate decrease to 1/4 +#define MAG_3110_OVERSAMPLE4 0x18 //128 sample rate decrease to 1/8 + +// read only 1 byte per axis +#define MAG_3110_FASTREAD 0x04 +// do one measurement (even if in standby mode) +#define MAG_3110_TRIGGER 0x02 +// put in active mode +#define MAG_3110_ACTIVE 0x01 + +// CTRL_REG2: AUTO_MRST_EN _ RAW MAG_RST _ _ _ _ _ +// reset sensor after each reading +#define MAG_3110_AUTO_MRST_EN 0x80 +// don't subtract user offsets +#define MAG_3110_RAW 0x20 +// reset magnetic sensor after too-large field +#define MAG_3110_MAG_RST 0x10 + +// DR_STATUS Register ZYXOW ZOW YOW XOW ZYXDR ZDR YDR XDR +#define MAG_3110_ZYXDR 0x08 + +/** + * MAG3110 Class to read X/Y/Z data from the magentometer + * + */ +class MAG3110 +{ +public: + /** + * Main constructor + * @param sda SDA pin + * @param sdl SCL pin + * @param addr addr of the I2C peripheral + */ + MAG3110(PinName sda, PinName scl); + /** + * Debug version of constructor + * @param sda SDA pin + * @param sdl SCL pin + * @param addr Address of the I2C peripheral + * @param pc Serial object to output debug messages + */ + MAG3110(PinName sda, PinName scl, Serial *pc); //pass serial for debug + /** + * Setup the Magnetometer + * + */ + MAG3110(PinName sda, PinName scl,float dateRate, int overSample); + void Overwrite_dr_osr(float dateRate,int overSample); + void Setdr(float dateRate); + void Setosr(int overSample); + + void begin(); + /** + * Read a register, return its value as int + * @param regAddr The address to read + * @return value in register + */ + int readReg(char regAddr); + /** + * Read a value from a pair of registers, return as int + * @param regAddr The address to read + * @return Value from 2 consecutive registers + */ + int readVal(char regAddr); + /** + * Calculate the heading + * @return heading in degrees + */ + float getHeading(); + /** + * Perform a read on the X, Y and Z values. + * @param xVal Pointer to X value + * @param yVal Pointer to Y value + * @param zVal Pointer to Z value + */ + void getValues(int *xVal, int *yVal, int *zVal); + /** + * Set the calibration parameters if required. + * @param minX Minimum value for X range + * @param maxX Maximum value for X range + * @param minY Minimum value for Y range + * @param maxY maximum value for Y range + */ + void setCalibration(int minX, int maxX, int minY, int maxY); + +private: + I2C _i2c; + int _i2c_address; + Serial *_pc; + bool _debug; + int _avgX, _avgY; + char dr; //date rate + char osr; //over sample rate + +}; +#endif
diff -r 000000000000 -r 2b49a387e831 MMA8451Q.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MMA8451Q.cpp Sat Feb 15 07:52:46 2014 +0000 @@ -0,0 +1,185 @@ +/* Copyright (c) 2010-2011 mbed.org, MIT License +* +* Permission is hereby granted, free of charge, to any person obtaining a copy of this software +* and associated documentation files (the "Software"), to deal in the Software without +* restriction, including without limitation the rights to use, copy, modify, merge, publish, +* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in all copies or +* substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include "MMA8451Q.h" + +#define INT_SOURCE 0x0C +#define REG_WHO_AM_I 0x0D +#define HP_FILTER_CUTOFF 0x0F +#define PULSE_CFG 0x21 +#define PULSE_SRC 0x22 +#define PULSE_THSX 0x23 +#define PULSE_THSY 0x24 +#define PULSE_THSZ 0x25 +#define PULSE_TMLT 0x26 +#define PULSE_LTCY 0x27 +#define PULSE_WIND 0x28 +#define REG_CTRL_REG_1 0x2A +#define CTRL_REG2 0x2B +#define CTRL_REG4 0x2D +#define CTRL_REG5 0x2E +#define REG_OUT_X_MSB 0x01 +#define REG_OUT_Y_MSB 0x03 +#define REG_OUT_Z_MSB 0x05 + +#define UINT14_MAX 16383 + +MMA8451Q::MMA8451Q(PinName sda, PinName scl, int addr) : m_i2c(sda, scl), m_addr(addr),dr(MMA8415Q_SAMPLE400) { + // activate the peripheral + uint8_t data[2] = {REG_CTRL_REG_1, 0x01}; + writeRegs(data, 2); +} + +MMA8451Q::~MMA8451Q() { } + +uint8_t MMA8451Q::getWhoAmI() { + uint8_t who_am_i = 0; + readRegs(REG_WHO_AM_I, &who_am_i, 1); + return who_am_i; +} + +float MMA8451Q::getAccX() { +//divide by 4096 b/c MMA output is 4096 counts per g so this f outputs accelorometer value formatted to g (gravity) + return (float(getAccAxis(REG_OUT_X_MSB))/4096.0); +} + +float MMA8451Q::getAccY() { + return (float(getAccAxis(REG_OUT_Y_MSB))/4096.0); +} + +float MMA8451Q::getAccZ() { + return (float(getAccAxis(REG_OUT_Z_MSB))/4096.0); +} + +void MMA8451Q::getAccAllAxis(float * res) { + res[0] = getAccX(); + res[1] = getAccY(); + res[2] = getAccZ(); +} + +int16_t MMA8451Q::getAccAxis(uint8_t addr) { + int16_t acc; + uint8_t res[2]; + readRegs(addr, res, 2); + + acc = (res[0] << 6) | (res[1] >> 2); + if (acc > UINT14_MAX/2) + acc -= UINT14_MAX; + + return acc; +} + +void MMA8451Q::setDoubleTap(void){ +//Implemented directly from Freescale's AN4072 +//Added to MMA8451Q lib + + uint8_t CTRL_REG1_Data; +// int adds; + uint8_t data[2] = {REG_CTRL_REG_1, dr}; //Sample Rate + + //400 Hz, Standby Mode + writeRegs(data,2); + + //Enable X, Y and Z Double Pulse with DPA = 0 no double pulse abort + data[0]=PULSE_CFG;data[1]=0x2A; + writeRegs(data,2); + + //SetThreshold 3g on X and Y and 5g on Z + //Note: Every step is 0.063g + //3 g/0.063g = 48 counts + //5g/0.063g = 79 counts + data[0]=PULSE_THSX;data[1]=0x30; + writeRegs(data,2);//Set X Threshold to 3g + data[0]=PULSE_THSY;data[1]=0x30; + writeRegs(data,2);//Set Y Threshold to 3g + data[0]=PULSE_THSZ;data[1]=0x4F; + writeRegs(data,2);//Set Z Threshold to 5g + + //Set Time Limit for Tap Detection to 60 ms LP Mode + //Note: 400 Hz ODR, Time step is 1.25 ms per step + //60 ms/1.25 ms = 48 counts + data[0]=PULSE_TMLT;data[1]=0x30; + writeRegs(data,2);//60 ms + + //Set Latency Time to 200 ms + //Note: 400 Hz ODR LPMode, Time step is 2.5 ms per step 00 ms/2.5 ms = 80 counts + data[0]=PULSE_LTCY;data[1]=0x50; + writeRegs(data,2);//200 ms + + //Set Time Window for second tap to 300 ms + //Note: 400 Hz ODR LP Mode, Time step is 2.5 ms per step + //300 ms/2.5 ms = 120 counts + data[0]=PULSE_WIND;data[1]=0x78; + writeRegs(data,2);//300 ms + + //Route INT1 to System Interrupt + data[0]=CTRL_REG4;data[1]=0x08; + writeRegs(data,2);//Enable Pulse Interrupt in System CTRL_REG4 + data[0]=CTRL_REG5;data[1]=0x08; + writeRegs(data,2);//Route Pulse Interrupt to INT1 hardware Pin CTRL_REG5 + + //Set the device to Active Mode + readRegs(0x2A,&CTRL_REG1_Data,1);//Read out the contents of the register + CTRL_REG1_Data |= 0x01; //Change the value in the register to Active Mode. + data[0]=REG_CTRL_REG_1; + data[1]=CTRL_REG1_Data; + writeRegs(data,2);//Write in the updated value to put the device in Active Mode +} + + +void MMA8451Q::readRegs(int addr, uint8_t * data, int len) { + char t[1] = {addr}; + m_i2c.write(m_addr, t, 1, true); + m_i2c.read(m_addr, (char *)data, len); +} + + + +void MMA8451Q::writeRegs(uint8_t * data, int len) { + m_i2c.write(m_addr, (char *)data, len); +} + +void MMA8451Q::Setdr(float dateRate) +{ + if (dateRate==800) + dr=MMA8415Q_SAMPLE800; + else if(dateRate==400) + dr=MMA8415Q_SAMPLE400; + else if(dateRate==200) + dr=MMA8415Q_SAMPLE200; + else if(dateRate==100) + dr=MMA8415Q_SAMPLE100; + else if(dateRate==50) + dr=MMA8415Q_SAMPLE50; + else if(dateRate==12.5) + dr=MMA8415Q_SAMPLE12_5; + else if(dateRate==6.25) + dr=MMA8415Q_SAMPLE6_25; + else if(dateRate==1.56) + dr=MMA8415Q_SAMPLE1_56; +} + +void MMA8451Q::Overwrite_dr(float dateRate) +{ + Setdr(dateRate); +// uint8_t data[2] = {REG_CTRL_REG_1, dr}; //Sample Rate + + //400 Hz, Standby Mode +// writeRegs(data,2); + setDoubleTap(); +} \ No newline at end of file
diff -r 000000000000 -r 2b49a387e831 MMA8451Q.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MMA8451Q.h Sat Feb 15 07:52:46 2014 +0000 @@ -0,0 +1,169 @@ +/* Copyright (c) 2010-2011 mbed.org, MIT License +* +* Permission is hereby granted, free of charge, to any person obtaining a copy of this software +* and associated documentation files (the "Software"), to deal in the Software without +* restriction, including without limitation the rights to use, copy, modify, merge, publish, +* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in all copies or +* substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#ifndef MMA8451Q_H +#define MMA8451Q_H +#define MMA8415Q_SAMPLE800 0x00 +#define MMA8415Q_SAMPLE400 0x08 +#define MMA8415Q_SAMPLE200 0x10 +#define MMA8415Q_SAMPLE100 0x18 +#define MMA8415Q_SAMPLE50 0x20 +#define MMA8415Q_SAMPLE12_5 0x28 +#define MMA8415Q_SAMPLE6_25 0x30 +#define MMA8415Q_SAMPLE1_56 0x38 + +#include "mbed.h" + +/** +* MMA8451Q accelerometer example +* +* @code +* #include "mbed.h" +* #include "MMA8451Q.h" +* +* #define MMA8451_I2C_ADDRESS (0x1d<<1) +* +* int main(void) { +* +* MMA8451Q acc(P_E25, P_E24, MMA8451_I2C_ADDRESS); +* PwmOut rled(LED_RED); +* PwmOut gled(LED_GREEN); +* PwmOut bled(LED_BLUE); +* +* while (true) { +* rled = 1.0 - abs(acc.getAccX()); +* gled = 1.0 - abs(acc.getAccY()); +* bled = 1.0 - abs(acc.getAccZ()); +* wait(0.1); +* } +* } +* @endcode +*/ +class MMA8451Q +{ +public: + /** + * MMA8451Q constructor + * + * @param sda SDA pin + * @param sdl SCL pin + * @param addr addr of the I2C peripheral + */ + MMA8451Q(PinName sda, PinName scl, int addr); + + /** + * MMA8451Q destructor + */ + ~MMA8451Q(); + + /** + * Get the value of the WHO_AM_I register + * + * @returns WHO_AM_I value + */ + uint8_t getWhoAmI(); + + /** + * Get X axis acceleration + * + * @returns X axis acceleration + */ + float getAccX(); + + /** + * Get Y axis acceleration + * + * @returns Y axis acceleration + */ + float getAccY(); + + /** + * Get Z axis acceleration + * + * @returns Z axis acceleration + */ + float getAccZ(); + + /** + * Get XYZ axis acceleration + * + * @param res array where acceleration data will be stored + */ + void getAccAllAxis(float * res); + + /** JK + * Setup Double Tap detection + + +Example: + +#include "mbed.h" +#include "MMA8451Q.h" + +#define MMA8451_I2C_ADDRESS (0x1d<<1) +#define ON 0 +#define OFF !ON + +//Setup the interrupts for the MMA8451Q +InterruptIn accInt1(PTA14); +InterruptIn accInt2(PTA15);//not used in this prog but this is the other int from the accelorometer + +uint8_t togstat=0;//Led status +DigitalOut bled(LED_BLUE); + + +void tapTrue(void){//ISR + if(togstat == 0){ + togstat = 1; + bled=ON; + } else { + togstat = 0; + bled=OFF; + } + +} + + +int main(void) { + + MMA8451Q acc(PTE25, PTE24, MMA8451_I2C_ADDRESS);//accelorometer instance + + acc.setDoubleTap();//Setup the MMA8451Q to look for a double Tap + accInt1.rise(&tapTrue);//call tapTrue when an interrupt is generated on PTA14 + + while (true) { + //Interrupt driven so nothing in main loop + } +} + + + */ + void setDoubleTap(void); + void Overwrite_dr(float dateRate); + void Setdr(float dateRate); +private: + I2C m_i2c; + int m_addr; + void readRegs(int addr, uint8_t * data, int len); + void writeRegs(uint8_t * data, int len); + int16_t getAccAxis(uint8_t addr); + char dr; + +}; + +#endif
diff -r 000000000000 -r 2b49a387e831 TSISensor.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TSISensor.cpp Sat Feb 15 07:52:46 2014 +0000 @@ -0,0 +1,276 @@ +/* Freescale Semiconductor Inc. + * (c) Copyright 2004-2005 Freescale Semiconductor, Inc. + * (c) Copyright 2001-2004 Motorola, Inc. + * + * mbed Microcontroller Library + * (c) Copyright 2009-2012 ARM Limited. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software + * and associated documentation files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or + * substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING + * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "mbed.h" +#include "TSISensor.h" + +#define NO_TOUCH 0 +#define SLIDER_LENGTH 40 //LENGTH in mm +#define TOTAL_ELECTRODE 3 + +#define TSI0a 0 +#define TSI1 1 +#define TSI2 2 +#define TSI3 3 +#define TSI4 4 +#define TSI5 5 +#define TSI6 6 +#define TSI7 7 +#define TSI8 8 +#define TSI9 9 +#define TSI10 10 +#define TSI11 11 +#define TSI12 12 +#define TSI13 13 +#define TSI14 14 +#define TSI15 15 + +/*Chose the correct TSI channel for the electrode number*/ +#define ELECTRODE0 TSI9 +#define ELECTRODE1 TSI10 +#define ELECTRODE2 TSI0a +#define ELECTRODE3 TSI1 +#define ELECTRODE4 TSI2 +#define ELECTRODE5 TSI3 +#define ELECTRODE6 TSI4 +#define ELECTRODE7 TSI5 +#define ELECTRODE8 TSI6 +#define ELECTRODE9 TSI7 +#define ELECTRODE10 TSI8 +#define ELECTRODE11 TSI11 +#define ELECTRODE12 TSI12 +#define ELECTRODE13 TSI13 +#define ELECTRODE14 TSI14 +#define ELECTRODE15 TSI15 + +#define THRESHOLD0 100 +#define THRESHOLD1 100 +#define THRESHOLD2 100 +#define THRESHOLD3 100 +#define THRESHOLD4 100 +#define THRESHOLD5 100 +#define THRESHOLD6 100 +#define THRESHOLD7 100 +#define THRESHOLD8 100 +#define THRESHOLD9 100 +#define THRESHOLD10 100 +#define THRESHOLD11 100 +#define THRESHOLD12 100 +#define THRESHOLD13 100 +#define THRESHOLD14 100 +#define THRESHOLD15 100 + +static uint8_t total_electrode = TOTAL_ELECTRODE; +static uint8_t elec_array[16]={ELECTRODE0,ELECTRODE1,ELECTRODE2,ELECTRODE3,ELECTRODE4,ELECTRODE5, + ELECTRODE6,ELECTRODE7,ELECTRODE8,ELECTRODE9,ELECTRODE10,ELECTRODE11, + ELECTRODE12,ELECTRODE13,ELECTRODE14,ELECTRODE15}; +static uint16_t gu16TSICount[16]; +static uint16_t gu16Baseline[16]; +static uint16_t gu16Threshold[16]={THRESHOLD0,THRESHOLD1,THRESHOLD2,THRESHOLD3,THRESHOLD4,THRESHOLD5, + THRESHOLD6,THRESHOLD7,THRESHOLD8,THRESHOLD9,THRESHOLD10,THRESHOLD11, + THRESHOLD12,THRESHOLD13,THRESHOLD14,THRESHOLD15}; +static uint16_t gu16Delta[16]; +static uint8_t ongoing_elec; +static uint8_t end_flag = 1; + +static uint8_t SliderPercentegePosition[2] = {NO_TOUCH,NO_TOUCH}; +static uint8_t SliderDistancePosition[2] = {NO_TOUCH,NO_TOUCH}; +static uint32_t AbsolutePercentegePosition = NO_TOUCH; +static uint32_t AbsoluteDistancePosition = NO_TOUCH; + +static void tsi_irq(); + +TSISensor::TSISensor() { + SIM->SCGC5 |= SIM_SCGC5_PORTB_MASK; + SIM->SCGC5 |= SIM_SCGC5_TSI_MASK; + + TSI0->GENCS |= (TSI_GENCS_ESOR_MASK + | TSI_GENCS_MODE(0) + | TSI_GENCS_REFCHRG(4) + | TSI_GENCS_DVOLT(0) + | TSI_GENCS_EXTCHRG(7) + | TSI_GENCS_PS(4) + | TSI_GENCS_NSCN(11) + | TSI_GENCS_TSIIEN_MASK + | TSI_GENCS_STPE_MASK + ); + + TSI0->GENCS |= TSI_GENCS_TSIEN_MASK; + + NVIC_SetVector(TSI0_IRQn, (uint32_t)&tsi_irq); + NVIC_EnableIRQ(TSI0_IRQn); + + selfCalibration(); +} + +void TSISensor::TSISensor_reset(void) { + SIM->SCGC5 |= SIM_SCGC5_PORTB_MASK; + SIM->SCGC5 |= SIM_SCGC5_TSI_MASK; + + TSI0->GENCS |= (TSI_GENCS_ESOR_MASK + | TSI_GENCS_MODE(0) + | TSI_GENCS_REFCHRG(4) + | TSI_GENCS_DVOLT(0) + | TSI_GENCS_EXTCHRG(7) + | TSI_GENCS_PS(4) + | TSI_GENCS_NSCN(11) + | TSI_GENCS_TSIIEN_MASK + | TSI_GENCS_STPE_MASK + ); + + TSI0->GENCS |= TSI_GENCS_TSIEN_MASK; + + //NVIC_SetVector(TSI0_IRQn, (uint32_t)&tsi_irq); + //NVIC_EnableIRQ(TSI0_IRQn); + + selfCalibration(); +} + +void TSISensor::selfCalibration(void) +{ + unsigned char cnt; + unsigned char trigger_backup; + + TSI0->GENCS |= TSI_GENCS_EOSF_MASK; // Clear End of Scan Flag + TSI0->GENCS &= ~TSI_GENCS_TSIEN_MASK; // Disable TSI module + + if(TSI0->GENCS & TSI_GENCS_STM_MASK) // Back-up TSI Trigger mode from Application + trigger_backup = 1; + else + trigger_backup = 0; + + TSI0->GENCS &= ~TSI_GENCS_STM_MASK; // Use SW trigger + TSI0->GENCS &= ~TSI_GENCS_TSIIEN_MASK; // Enable TSI interrupts + + TSI0->GENCS |= TSI_GENCS_TSIEN_MASK; // Enable TSI module + + for(cnt=0; cnt < total_electrode; cnt++) // Get Counts when Electrode not pressed + { + TSI0->DATA = ((elec_array[cnt] << TSI_DATA_TSICH_SHIFT) ); + TSI0->DATA |= TSI_DATA_SWTS_MASK; + while(!(TSI0->GENCS & TSI_GENCS_EOSF_MASK)); + TSI0->GENCS |= TSI_GENCS_EOSF_MASK; + gu16Baseline[cnt] = (TSI0->DATA & TSI_DATA_TSICNT_MASK); + } + + TSI0->GENCS &= ~TSI_GENCS_TSIEN_MASK; // Disable TSI module + TSI0->GENCS |= TSI_GENCS_TSIIEN_MASK; // Enale TSI interrupt + if(trigger_backup) // Restore trigger mode + TSI0->GENCS |= TSI_GENCS_STM_MASK; + else + TSI0->GENCS &= ~TSI_GENCS_STM_MASK; + + TSI0->GENCS |= TSI_GENCS_TSIEN_MASK; // Enable TSI module + + TSI0->DATA = ((elec_array[0]<<TSI_DATA_TSICH_SHIFT) ); + TSI0->DATA |= TSI_DATA_SWTS_MASK; +} + +void TSISensor::sliderRead(void ) { + if(end_flag) { + end_flag = 0; + if((gu16Delta[0] > gu16Threshold[0])||(gu16Delta[1] > gu16Threshold[1])) { + SliderPercentegePosition[0] = (gu16Delta[0]*100)/(gu16Delta[0]+gu16Delta[1]); + SliderPercentegePosition[1] = (gu16Delta[1]*100)/(gu16Delta[0]+gu16Delta[1]); + SliderDistancePosition[0] = (SliderPercentegePosition[0]* SLIDER_LENGTH)/100; + SliderDistancePosition[1] = (SliderPercentegePosition[1]* SLIDER_LENGTH)/100; + AbsolutePercentegePosition = ((100 - SliderPercentegePosition[0]) + SliderPercentegePosition[1])/2; + AbsoluteDistancePosition = ((SLIDER_LENGTH - SliderDistancePosition[0]) + SliderDistancePosition[1])/2; + } else { + SliderPercentegePosition[0] = NO_TOUCH; + SliderPercentegePosition[1] = NO_TOUCH; + SliderDistancePosition[0] = NO_TOUCH; + SliderDistancePosition[1] = NO_TOUCH; + AbsolutePercentegePosition = NO_TOUCH; + AbsoluteDistancePosition = NO_TOUCH; + } + } +} + +float TSISensor::readPercentage() { + sliderRead(); + return (float)AbsolutePercentegePosition/100.0; +} + +uint8_t TSISensor::readDistance() { + sliderRead(); + return AbsoluteDistancePosition; +} + +uint16_t TSISensor::readValue(uint8_t index) +{ + return gu16TSICount[index]; +} + +static void changeElectrode(void) +{ + int16_t u16temp_delta; + + gu16TSICount[ongoing_elec] = (TSI0->DATA & TSI_DATA_TSICNT_MASK); // Save Counts for current electrode + u16temp_delta = gu16TSICount[ongoing_elec] - gu16Baseline[ongoing_elec]; // Obtains Counts Delta from callibration reference + if(u16temp_delta < 0) + gu16Delta[ongoing_elec] = 0; + else + gu16Delta[ongoing_elec] = u16temp_delta; + + //Change Electrode to Scan + if(total_electrode > 1) + { + if((total_electrode-1) > ongoing_elec) + ongoing_elec++; + else + ongoing_elec = 0; + + TSI0->DATA = ((elec_array[ongoing_elec]<<TSI_DATA_TSICH_SHIFT) ); + TSI0->DATA |= TSI_DATA_SWTS_MASK; + } +} + +void tsi_irq(void) +{ + end_flag = 1; + TSI0->GENCS |= TSI_GENCS_EOSF_MASK; // Clear End of Scan Flag + changeElectrode(); +} + +void TSISensor::Overwrite_ps_nscn(int ps,int nscn) +{ + + TSI0->GENCS |= (TSI_GENCS_ESOR_MASK + | TSI_GENCS_MODE(0) + | TSI_GENCS_REFCHRG(4) + | TSI_GENCS_DVOLT(0) + | TSI_GENCS_EXTCHRG(7) + | TSI_GENCS_PS(ps) + | TSI_GENCS_NSCN(nscn) + | TSI_GENCS_TSIIEN_MASK + | TSI_GENCS_STPE_MASK + ); + + TSI0->GENCS |= TSI_GENCS_TSIEN_MASK; + + //NVIC_SetVector(TSI0_IRQn, (uint32_t)&tsi_irq); + //NVIC_EnableIRQ(TSI0_IRQn); + + selfCalibration(); +} \ No newline at end of file
diff -r 000000000000 -r 2b49a387e831 TSISensor.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TSISensor.h Sat Feb 15 07:52:46 2014 +0000 @@ -0,0 +1,74 @@ +/* Freescale Semiconductor Inc. + * (c) Copyright 2004-2005 Freescale Semiconductor, Inc. + * (c) Copyright 2001-2004 Motorola, Inc. + * + * mbed Microcontroller Library + * (c) Copyright 2009-2012 ARM Limited. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software + * and associated documentation files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or + * substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING + * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef TSISENSOR_H +#define TSISENSOR_H + +/** +* TSISensor example +* +* @code +* #include "mbed.h" +* #include "TSISensor.h" +* +* int main(void) { +* PwmOut led(LED_GREEN); +* TSISensor tsi; +* +* while (true) { +* led = 1.0 - tsi.readPercentage(); +* wait(0.1); +* } +* } +* @endcode +*/ +class TSISensor { +public: + /** + * Initialize the TSI Touch Sensor + */ + TSISensor(); + + /** + * Read Touch Sensor percentage value + * + * @returns percentage value between [0 ... 1] + */ + float readPercentage(); + + /** + * Read Touch Sensor distance + * + * @returns distance in mm. The value is between [0 ... 40] + */ + uint8_t readDistance(); + uint16_t readValue(uint8_t); + void TSISensor_reset(void); + void Overwrite_ps_nscn(int ps,int nscn); + +private: + void sliderRead(void); + void selfCalibration(void); +}; + +#endif
diff -r 000000000000 -r 2b49a387e831 main.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Sat Feb 15 07:52:46 2014 +0000 @@ -0,0 +1,354 @@ +#include "mbed.h" +#include "TSISensor.h" +#include "MMA8451Q.h" +#include "MAG3110.h" +#include "EventFramework/EventFramework.h" +#include <cstdlib> + +#define OFF 0 +#define ON 1 + +#define DEBUG + +PwmOut rled(PTE29); +PwmOut gled(PTD5); + +Serial pc(USBTX, USBRX); + +MMA8451Q acc51(PTE25, PTE24, 0x1D<<1); +MAG3110 mag(PTE25, PTE24); +AnalogIn lightSensor(PTE22); +TSISensor tsi; +AnalogIn sinewave(PTB1); + +// labels for different data channel +char MAG_X = 0x00; +char MAG_Y = 0x01; +char MAG_Z = 0x02; +char MAG_H = 0x03; +char ACC_X = 0x04; +char ACC_Y = 0x05; +char ACC_Z = 0x06; +char LIT_X = 0x07; +char TOU_X = 0x08; +char SIN_X = 0x09; + + +int MAG_STATUS = OFF; +int ACCL_STATUS = OFF; +int LIGHT_STATUS = OFF; +int TOUCH_STATUS = OFF; +int SINE_STATUS = OFF; + +Timer t1; +Timer t2; +Timer t3; +Timer t4; +Timer t5; + +//time threshold, equals to 1/sampling_rate +int interval1 = 10000; +int interval2 = 10000; +int interval3 = 10000; +int interval4 = 10000; +int interval5 = 10000; + +// framework creation with cooperative scheduling mechanism. +EventFramework kernel(EventFramework::SCHED_VALUE_COOPERATIVE); +// Events creation +Event accl_Evt(0); +Event mag_Evt(0); +Event light_Evt(0); +Event touch_Evt(0); +Event sine_Evt(0); +// EventHandlers creation +EventHandler eh_accl(0); +EventHandler eh_mag(0); +EventHandler eh_light(0); +EventHandler eh_touch(0); +EventHandler eh_sine(0); +// declaration of event dispatching functions that will be attached to previous EventHandlers +EventDispatchingRoutine ev_accl_handle_func; +EventDispatchingRoutine ev_mag_handle_func; +EventDispatchingRoutine ev_light_handle_func; +EventDispatchingRoutine ev_touch_handle_func; +EventDispatchingRoutine ev_sine_handle_func; + +int START = OFF; + +void sendint(char label,int x){ + char *p = (char *)&x; + pc.putc(label); + pc.putc(*p); + pc.putc(*(p+1)); + pc.putc(*(p+2)); + pc.putc(*(p+3)); + } + +void sendfloat(char label,float x){ + char *p = (char *)&x; + pc.putc(label); + pc.putc(*p); + pc.putc(*(p+1)); + pc.putc(*(p+2)); + pc.putc(*(p+3)); + } + +void calXY() //magnetometer calibration: finding max and min of X, Y axis +{ + int tempXmax, tempXmin, tempYmax, tempYmin, newX, newY; + + rled = ON; + + printf("Waiting for initial press\n"); + // Wait for slider to be pressed + while( tsi.readDistance() == 0 ) { + rled = ON; + wait(0.2); + rled = OFF; + wait(0.2); + } + + printf("Waiting for release\n"); + + // Wait for release + while( tsi.readDistance() != 0 ) { + rled = OFF; + wait(0.2); + rled = ON; + wait(0.2); + } + rled = OFF; + wait(0.5); + + printf("Rotate\n"); + + tempXmax = tempXmin = mag.readVal(MAG_OUT_X_MSB); + tempYmax = tempYmin = mag.readVal(MAG_OUT_Y_MSB); + + while(tsi.readDistance() == 0) { + gled = ON; + wait(0.1); + gled = OFF; + wait(0.1); + newX = mag.readVal(MAG_OUT_X_MSB); + newY = mag.readVal(MAG_OUT_Y_MSB); + if (newX > tempXmax) tempXmax = newX; + if (newX < tempXmin) tempXmin = newX; + if (newY > tempYmax) tempYmax = newY; + if (newY < tempYmin) tempYmin = newY; + } + + mag.setCalibration( tempXmin, tempXmax, tempYmin, tempYmax ); + + // Wait for release + while( tsi.readDistance() != 0 ) { + gled = OFF; + wait(0.2); + gled = ON; + wait(0.2); + } + gled = OFF; + wait(1.0); +} + +uint32_t ev_accl_handle_func(void* me, void* args){ + float temp_x = acc51.getAccX(); + float temp_y = acc51.getAccY(); + float temp_z = acc51.getAccZ(); + __disable_irq(); + sendfloat(ACC_X,temp_x); + sendfloat(ACC_Y,temp_y); + sendfloat(ACC_Z,temp_z); + __enable_irq(); +} + uint32_t ev_mag_handle_func(void* me, void* args){ + int temp_x = 0, temp_y = 0, temp_z = 0; + float temp_h = mag.getHeading(); + mag.getValues(&temp_x, &temp_y, &temp_z); + __disable_irq(); + sendint(MAG_X,temp_x); + sendint(MAG_Y,temp_y); + sendint(MAG_Z,temp_z); + sendfloat(MAG_H,temp_h); + __enable_irq(); +} + uint32_t ev_light_handle_func(void* me, void* args){ + float temp_x = lightSensor; + __disable_irq(); + sendfloat(LIT_X,temp_x); + __enable_irq(); +} + uint32_t ev_touch_handle_func(void* me, void* args){ + float temp_x = tsi.readPercentage();; + __disable_irq(); + sendfloat(TOU_X,temp_x); + __enable_irq(); +} + uint32_t ev_sine_handle_func(void* me, void* args){ + float temp_x = sinewave.read();; + __disable_irq(); + sendfloat(SIN_X,temp_x); + __enable_irq(); +} +void pc_command(){ + kernel.SaveContext(); + char command = pc.getc(); + float sr; + char temp[4]; + + switch(command) + { + case 0xEE : // configuration or reconfiguration header + + command = pc.getc(); + if (command == 0x01){ // check the status of magnetometer + MAG_STATUS = ON;// turn it on + temp[0] = pc.getc(); + temp[1] = pc.getc(); + temp[2] = pc.getc(); + temp[3] = pc.getc(); + sr = *(float*)temp;//sampling rate + interval1 =(int) 1/sr *1000;//threshold + t1.reset();//timer reset + } + else{ + MAG_STATUS = OFF;//turn it off + t1.stop(); + } + command = pc.getc(); + if (command == 0x01){ // check the status of accelerometer + ACCL_STATUS = ON; + temp[0] = pc.getc(); + temp[1] = pc.getc(); + temp[2] = pc.getc(); + temp[3] = pc.getc(); + sr = *(float*)temp; + interval2 =(int) 1/sr *1000; + t2.reset(); + } + else{ + ACCL_STATUS = OFF; + t2.stop(); + } + command = pc.getc(); + if (command == 0x01){ // check the status of the light sensor + LIGHT_STATUS = ON; + temp[0] = pc.getc(); + temp[1] = pc.getc(); + temp[2] = pc.getc(); + temp[3] = pc.getc(); + sr = *(float*)temp; + interval3 =(int) 1/sr *1000; + t3.reset(); + } + else{ + LIGHT_STATUS = OFF; + t3.stop(); + } + command = pc.getc(); + if (command == 0x01){ // check the status of the touch sensor + TOUCH_STATUS = ON; + temp[0] = pc.getc(); + temp[1] = pc.getc(); + temp[2] = pc.getc(); + temp[3] = pc.getc(); + sr = *(float*)temp; + interval4 =(int) 1/sr *1000; + t4.reset(); + } + else{ + TOUCH_STATUS = OFF; + t4.stop(); + } + command = pc.getc(); + if (command == 0x01){ // check the status of the sine wave receiver + SINE_STATUS = ON; + temp[0] = pc.getc(); + temp[1] = pc.getc(); + temp[2] = pc.getc(); + temp[3] = pc.getc(); + sr = *(float*)temp; + interval5 =(int) 1/sr *1000; + t5.reset(); + } + else{ + SINE_STATUS = OFF; + t5.stop(); + } + START = ON; + rled = ON; + break; + } + kernel.RestoreContext(); + } + +int main() +{ + // events must be registered into the framework + kernel.AddEvent(&mag_Evt); + kernel.AddEvent(&accl_Evt); + kernel.AddEvent(&light_Evt); + kernel.AddEvent(&touch_Evt); + kernel.AddEvent(&sine_Evt); + + eh_mag.Attach(&ev_mag_handle_func); + eh_accl.Attach(&ev_accl_handle_func); + eh_light.Attach(&ev_light_handle_func); + eh_touch.Attach(&ev_touch_handle_func); + eh_sine.Attach(&ev_sine_handle_func); + + // handlers are registered into the kernel to listen to specific events. [eh1] listens to [ev1], [eh2] listens to [ev2]. + kernel.AddEventListener(&mag_Evt, &eh_mag); + kernel.AddEventListener(&accl_Evt, &eh_accl); + kernel.AddEventListener(&light_Evt, &eh_light); + kernel.AddEventListener(&touch_Evt, &eh_touch); + kernel.AddEventListener(&sine_Evt, &eh_sine); + calXY(); + pc.attach(&pc_command); + + while(START == OFF){ + pc.putc(0xFF); + } + pc.putc(0xFE); + + t1.start(); + t2.start(); + t3.start(); + t4.start(); + t5.start(); + // the event-driven kernel starts its operation. + while(1) { + kernel.Schedule(); + if (MAG_STATUS == ON){ + if (t1.read_ms()>interval1){ + kernel.PublishEvent(&mag_Evt, 0); + t1.reset(); + } + } + if (ACCL_STATUS == ON){ + if (t2.read_ms()>interval2){ + kernel.PublishEvent(&accl_Evt, 0); + t2.reset(); + } + } + if (LIGHT_STATUS == ON){ + if (t3.read_ms()>interval3){ + kernel.PublishEvent(&light_Evt, 0); + t3.reset(); + } + } + if (TOUCH_STATUS == ON){ + if (t4.read_ms()>interval4){ + kernel.PublishEvent(&touch_Evt, 0); + t4.reset(); + } + } + if (SINE_STATUS == ON){ + if (t5.read_ms()>interval5){ + kernel.PublishEvent(&sine_Evt, 0); + t5.reset(); + } + } + } +} \ No newline at end of file
diff -r 000000000000 -r 2b49a387e831 mbed.bld --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Sat Feb 15 07:52:46 2014 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/824293ae5e43 \ No newline at end of file