📄 micasbtest1m.nc
字号:
// $Id: MicaSBTest1M.nc,v 1.3 2003/10/07 21:44:53 idgay Exp $/* tab:4 * "Copyright (c) 2000-2003 The Regents of the University of California. * All rights reserved. * * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose, without fee, and without written agreement is * hereby granted, provided that the above copyright notice, the following * two paragraphs and the author appear in all copies of this software. * * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS." * * Copyright (c) 2002-2003 Intel Corporation * All rights reserved. * * This file is distributed under the terms in the attached INTEL-LICENSE * file. If you do not find these files, copies can be found by writing to * Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA, * 94704. Attention: Intel License Inquiry. *//* Authors: Alec Woo Su Ping * Intel Research Berkeley Lab * *//* * Implementation for MicaSBTest1 application. * * MicaSBTest1 is an application that test out the magnetometer, * accelerometer, and temperature sensor. It demonstrates how to access * the data from each individual sensors, how to perform real time * "calibration", and how to filter and process sensory data for * the magnetometer. * * The test cases for the accelerometer and the temperature sensor * is very simple. The raw 10 bit data from these sensors are sent * over the UART for visual inspection. The format of the packet looks like * the following: (30 bytes long, each sensor value is 2 bytes long) * * [TEMP ACCEL_X ACCEL_Y] [TEMP ACCEL_X ACCEL_Y] [TEMP ACCEL_X ACCEL_Y] [TEMP ACCEL_X ACCEL_Y] [TEMP ACCEL_X ACCEL_Y] * * * For the magnetometer, one can visually look at the LEDs to see * if it is working. * * RED - self calibration is being done * GREEN - idle -> no magnetic field event detected * Yellow - event triggered: either X or Y axis has event detected. * *//**************************************************************************** tab:4SENSOR INFONumber of Channels 2 (x,Y)MAGNETOMETER SPECIFICATIONS ---caution: these values are based on MICA SENSOR component values asof 02Feb02SENSOR Honeywell HMC1002SENSITIVITY 3.2mv/Vex/gaussEXCITATION 3.0V (nominal)AMPLIFIER GAIN 2262 Stage 1 29 Stage 2 78 ADC Input 22mV/mgaussADC Sensitivity 6.4cnts/mgaussADC Resolution 0.13mgauss/bit * @author Alec Woo Su Ping * @author Intel Research Berkeley Lab *****************************************************************************/module MicaSBTest1M { provides interface StdControl; uses { interface Timer; interface Leds; interface MagSetting; interface StdControl as CommControl; interface StdControl as AccelControl; interface StdControl as TempControl; interface ADC as AccelX; interface ADC as AccelY; interface StdControl as MagControl; interface ADC as MagX; interface ADC as MagY; interface ADC as TempADC; interface SendMsg as Send; }}implementation { // declar module static variables here enum { MAG_OFFSET_MIDSCALE = 128, MAG_ADC_MIDSCALE = 512, MAG_ADC_ALMOSTMAX = 700, //only 50% fs range due to instrumentation amp rails MAG_ADC_ALMOSTMIN = 300 }; enum{ I2C_IDLE = 0,//I2C not busy I2C_POTX , //I2C Busy writing to Mag X pot I2C_POTY //I2C Busy writing to Mag Y pot }; //Data Acquisition modes/states enum { DM_IDLE = 0, //nothing DM_AUTOZERO_START, //start autozeroing DM_AUTOZERO , //autozero the magnetometers DM_UNDEFINED , DM_NORMAL, //standard daq DM_STARTUP //startup holdoff }; //Event Detection states enum { EV_UNDER=0, //under threshold EV_OVER =1, //over threshold EV_IDLE =0, //no signal detected EV_ADC = 1, //ADC data over Amplitude threshold EV_TIME = 2 //Data over Time and Amplitude threshold }; enum { BUFR_SHIFT_BITS =2, //NOTE: gcc doesn't process " BUFR_WSAMPLES (2 << BUFR_SHIFT_BITS)" properly // so following define must be hand-entered for any change to BUFR_SHIFT_BITS BUFR_WSAMPLES= 4 // history buffer size }; //--- Magnetometer Thresholds 6.4 ADCCounts/milliGauss (0.13mgauss/bit)(nominal) enum { MAGX_THRESHOLD = 10, //trigger threshold offset from quiescent baseline in adc counts) MAGY_THRESHOLD = 10, //trigger threshold offset from quiescent (in adc counts) TIME_OVER_MIN = 3, //time over threshold to qualify as an event (noise suppress) TIME_UNDER_MIN =-3, //time under threshold to qualify as event removed NOTE SIGN!!! TIME_OVER_MAX =120, //over threshold for so long should establish a new baseline RE_ZERO_COUNT =30, //#of samples in saturation requiring a re-zero of mag STARTUP_HOLDOFF=120, // Clock ticks for startup to complete before autozeroing BASELINE_COUNT = 32, //# of BUFR_WSAMPLES-averaged data:beware of overflows BASELINE_SHIFT_BITS =5 // must keep this value consistent with previous value }; /* Data stored for each sample reading */ typedef struct { short x_val; short y_val; }magsz_data_struct; typedef struct { int index; // array address to which next sample will be stored int minCount; // when count reaches BUFR_WSAMPLES, averaging can start int xsum; // most-recent sum of x mag values int ysum; // ditto for y int trgHoldoffCount; //number of samples to delay after trigger before testing again magsz_data_struct adata[BUFR_WSAMPLES]; // 4 data points per eprom write => 16 bytes }bufr_data_struct; //local function declarations void InitSampling(); /* Define the module variables */ /* Race conditions are avoided by the sequential nature of the application */ TOS_Msg buffer1; // double buffer TOS_Msg buffer2; // double buffer norace TOS_MsgPtr msgPtr; //temperature message buffer norace TOS_MsgPtr oldmsgPtr; //accelerometer message buffer norace char msgIndex; // index to the array char msg_pending; // true if message pending norace char stepdown; // scaling variable char samp_on; char DAQMode; //Data Aquisition state char EVState; //Event state char cMagXOffset; //Magnetometer offset char cMagYOffset; //Magnetometer offset char I2CBusy; //flag indicating offset POT is being written to int cAZBit; //bit mask for Autozero operation int iTimeinSaturation; // #of sequentialsamples accumulated in saturation int iTimerThresholdCummulative; int iTimerThreshold; //##of sequential over threshold - int avgMagX; //n-second base level average of magnetometer values, continuously updated int avgMagY; int avgMagXSum; //summed baseline - simplifies computation of moving average int avgMagYSum; int baselineCount; // 16 4-sample averages are averaged to get baseline norace bufr_data_struct bufr_data; //stores magnetometer data for averaging for threshold detection task void SendTask() { call Send.send(TOS_UART_ADDR, 29, msgPtr); } /** * Task for filtering the 2 axis data from the magnetometer and performm event detection. * * @return returns void. **/ task void FILTER_DATA(){ int xsum, ysum; int i; char NextDAQMode; char NextEV; // Default next DAQMode state is current state NextDAQMode = DAQMode; NextEV = EVState; //default is to stay in current state //increment buffer array index bufr_data.index++; if (bufr_data.index >= BUFR_WSAMPLES) bufr_data.index = 0; //Test threshold //test whether the buffer has been filled at least once. if(bufr_data.minCount < (BUFR_WSAMPLES-1)){ //if not, increment buffer count bufr_data.minCount++; }else //if so, calculate averages and set led appropriately. { //calculate averages xsum = 0; ysum = 0; for(i=0;i<BUFR_WSAMPLES;i++) { xsum += bufr_data.adata[i].x_val; ysum += bufr_data.adata[i].y_val; } xsum = xsum >> BUFR_SHIFT_BITS; ysum = ysum >> BUFR_SHIFT_BITS; bufr_data.xsum = xsum; bufr_data.ysum = ysum; //either use data for baseline averaging or for threshold test if(baselineCount < BASELINE_COUNT) { if(baselineCount==0 ) { //initialize average avgMagXSum = 0; avgMagYSum = 0; } //when baselineCount reaches limit, perform 16x4 sample average baselineCount++; avgMagXSum += xsum; avgMagYSum += ysum; if(baselineCount < BASELINE_COUNT) { bufr_data.minCount = 0; //start next 4-sample average //turn off all leds but 1 to keep PS offsets balanced TOSH_SET_RED_LED_PIN(); TOSH_SET_YELLOW_LED_PIN(); TOSH_CLR_GREEN_LED_PIN(); //LED ON (RED LED on MICA) } else{ avgMagX = avgMagXSum >> BASELINE_SHIFT_BITS; avgMagY = avgMagYSum >> BASELINE_SHIFT_BITS; TOSH_SET_GREEN_LED_PIN(); //LED OFF (RED LED on MICA) } } // end baseline averaging else //------- DAQMode states -------------------------------------- { // Have baseline data in avg vars - Handle DAQStates switch( DAQMode ) { case DM_AUTOZERO_START: //--AUTOZERO_START call Leds.redOn(); //Red led on cMagXOffset = MAG_OFFSET_MIDSCALE; cMagYOffset = MAG_OFFSET_MIDSCALE; cAZBit = MAG_OFFSET_MIDSCALE; //set MSB -!!NOTE:using int because no unsignedchar??? I2CBusy = I2C_POTX; //I2C bus will be busy setting pot X call MagSetting.gainAdjustX(cMagXOffset); // WRITE_DONE Event will initiate ADC baseline measurement NextDAQMode = DM_AUTOZERO; // change state //dmazstart break; //azstart case DM_AUTOZERO: //--AUTOZERO_OPERATION if( I2CBusy ){ break; } //no can do // Evaluate ADC data if( (xsum)<MAG_ADC_MIDSCALE) { //Mag X Offset //clear previous bit in offset pot cMagXOffset = cMagXOffset& ~cAZBit; } if( (ysum)<MAG_ADC_MIDSCALE) { //Mag Y offset //clear previous bit in offset pot cMagYOffset= cMagYOffset & ~cAZBit; } cAZBit = cAZBit>>1; // Set next bit in offset pots if( cAZBit==0) { // autozero operation finished baselineCount= 0; //Establish a new base line for threshold detection NextDAQMode = DM_NORMAL; //return to general data acquisition } else { //set next bit in offset pots and measure ADC response cMagXOffset = cMagXOffset | cAZBit; cMagYOffset = cMagYOffset | cAZBit; //set Offset and measure baseline data I2CBusy = I2C_POTX; //I2C bus will be busy setting pot call MagSetting.gainAdjustX( cMagXOffset); // WRITE_DONE Event will initiate ADC baseline measurement } //if cAZBit call Leds.redToggle(); //led on break;//DM_AUTOZERO case DM_NORMAL: //---DM_NORMAL //Do NOT evaluate data if in trigger hold-off if( bufr_data.trgHoldoffCount > 0){ bufr_data.trgHoldoffCount--; iTimerThreshold = 0; //reset the count NextEV = EV_UNDER; //clear the Event bufr_data.minCount = 0; //force buffer to flush during holdoff break; } // don't evaluate adc data during RF transmission & holdoff // Update moving average baseline avgMagXSum = xsum + avgMagXSum - ( avgMagXSum>>BASELINE_SHIFT_BITS); avgMagX = avgMagXSum >> BASELINE_SHIFT_BITS; avgMagYSum = ysum + avgMagYSum - ( avgMagYSum>>BASELINE_SHIFT_BITS); avgMagY= avgMagYSum >> BASELINE_SHIFT_BITS; // state = EV_IDLE; if((xsum > ( avgMagX+MAGX_THRESHOLD)) || (xsum < ( avgMagX-MAGX_THRESHOLD))) { iTimerThresholdCummulative++; iTimerThreshold++; //update time over } else if((ysum > ( avgMagY+MAGY_THRESHOLD)) || (ysum < ( avgMagY-MAGY_THRESHOLD))) { iTimerThresholdCummulative++; iTimerThreshold++; //update time over } //state = EV_ADC; else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -