Squirrels have fuzzy tails.
0 Members and 1 Guest are viewing this topic.
/* Truth Wristband!!!// A wearable device that dynamically reflects the your / psycho-emotional response to the world, promoting internal / states to be externalized and made into interactive forms / of expression. Measuring the galvanic skin response / (a marker of emotional arousal commonly used in lie detector / tests), this device’s lights turn from blue to red as the / wearer becomes aroused. Ask the wearer an evocative question / and reveal his or her inner Truth.// Skin resistance changes -> B->R waves over 5 LEDs/ Fs = 50 Hz/ 5 sec calibration delay on startup/ Smoothed to 3.33Hz/ Average skin resistance calculated using 1 second decay constant/ VDD = 2.4-3V// Written by Sean M. Montgomery, 2009/02/ http://www.produceconsumerobot.com/truth/// Truth Wristband by Sean M. Montgomery is licensed under a / Creative Commons Attribution-Noncommercial-Share Alike 3.0 / United States License/ */#include <p18f25k20.h>#include <adc.h>#include <timers.h>#include <math.h>#include "SetOutputs.h"void high_isr(void);void init(void);void GetData(void);// counter values to convert A/D sampling to 20msunsigned char t1_20msConversion = 5; unsigned char t1_20msCounter = 0;static unsigned char onBit = 1; // set ON output value// counter to set startup calibration timestatic int startupCounter = 0;static int maxStartupCounter = 250; //50Hz * 5secstatic float dataBuffer = 0.0; // current skin resistance valuestatic float meanData = 0.0; // average skin resistance value// period over which data is smoothedstatic float smoothPeriod = 1.0;static const float maxSmoothPeriod = 15.0; //50Hz/15=3.33Hz // period over which average skin resistance is calculated static float normPeriod = 1.0;static const float maxNormPeriod = 50.0; //50Hz * 1sec// initializes output arrays to use the SetOutputs function#define NUMLEDS 5#define NUMLEDPINS 10volatile near unsigned char * outPorts[NUMLEDPINS] = { &LATC, &LATC, &LATC, // for RGB LEDs// &LATA, // for RBG LEDs &LATA, &LATC, &LATC, &LATB, &LATB, &LATB, &LATA, };unsigned char outBits[NUMLEDPINS] = { 0b00001000, // for RGB LEDs// 0b00000100, // for RBG LEDs 0b00000010, 0b00000001, // for RGB LEDs// 0b01000000, // for RBG LEDs 0b10000000, 0b00100000, // for RGB LEDs// 0b01000000, // for RBG LEDs 0b10000000, 0b00000001, // for RGB LEDs// 0b00000010, // for RBG LEDs 0b00000100, 0b00001000, // for RGB LEDs// 0b00010000, // for RBG LEDs 0b00000100 };unsigned char outVals[NUMLEDPINS] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };// RGB pointers for keeping track of LED outputstypedef struct { unsigned char * r; unsigned char * g; unsigned char * b;} RGBpointers;RGBpointers outLEDs[NUMLEDS]; void main(void) { unsigned short j; float diffData; float threshold; float threshFactor = 0.24; float threshOffset = 0.01; unsigned char hue = 0; init(); while(1) { // turn all lights red for startup calibration if (startupCounter < maxStartupCounter) { for (j=0; j<NUMLEDS; j++) { *outLEDs[j].r = onBit; *outLEDs[j].b = !onBit; } } else { // subtract baseline average diffData = meanData - dataBuffer; // determine if skin resistance deviation crosses the // threshold for each LED for (j=0; j<NUMLEDS; j++) { // uses cubic function for thresholds across 5 LEDs threshold = (float) (j*j*j); threshold = ((threshold*threshFactor)+threshOffset) ; if (diffData > threshold) { *outLEDs[j].r = onBit; *outLEDs[j].b = !onBit; } else { *outLEDs[j].r = !onBit; *outLEDs[j].b = onBit; } } } }}//interrupt code:#pragma code high_interrupt=0x08void high_interrupt(void) { _asm goto high_isr _endasm}#pragma code//handle interrupts#pragma interrupt high_isrvoid high_isr(void) { int j; if ( INTCONbits.TMR0IF ) { // timer 0 INTCONbits.TMR0IF = 0; WriteTimer0(131); // converts timer triggers to 20ms t1_20msCounter++; if (t1_20msCounter == t1_20msConversion) { t1_20msCounter = 0; // Set the LEDs SetOutputs(NUMLEDPINS,outVals,outPorts,outBits); GetData(); // reads data from A/D if (startupCounter < maxStartupCounter) { startupCounter++; } } }}// Load data into dataBuffervoid GetData(void) { unsigned int tempData; while( BusyADC() ); // Wait for completion tempData = ReadADC(); // Read result ConvertADC(); // Start conversion // smooth the data dataBuffer = dataBuffer*(smoothPeriod-1.0); dataBuffer = dataBuffer + ((float) tempData); dataBuffer = dataBuffer/smoothPeriod; if (smoothPeriod < maxSmoothPeriod) { smoothPeriod = smoothPeriod + 1.0; } else { // average the data to calculate baseline skin resistance meanData = meanData*(normPeriod-1.0); meanData = meanData + dataBuffer; meanData = meanData/normPeriod; if (normPeriod < maxNormPeriod) { normPeriod = normPeriod + 1.0; } } } void init(void) { unsigned char j; // map output vector onto red and blue arrays for (j=0;j<NUMLEDS;j++) { outLEDs[j].r = &outVals[j*2]; outLEDs[j].b = &outVals[j*2+1]; *outLEDs[j].r = onBit; *outLEDs[j].b = !onBit; } // Set INTOSC bits; 110=8MHz OSCCONbits.IRCF2 = 1; OSCCONbits.IRCF1 = 1; OSCCONbits.IRCF0 = 0; // select system clock; 1x=internal osc, 00=primary oscillator OSCCONbits.SCS1 = 0; OSCCONbits.SCS0 = 0; OSCTUNEbits.PLLEN = 1; // turn on 4x PLL clock multiplier //set outputs TRISA = 0; TRISB = 0; TRISC = 0; PORTA = 0b11111111; PORTB = 0b11111111; PORTC = 0b11111111; // set inputs TRISAbits.TRISA5 = 1; TRISAbits.TRISA3 = 1; // set analog channels ANSELbits.ANS4 = 1; ANSELbits.ANS3 = 1; // set up timer OpenTimer0(TIMER_INT_ON & // interrupt on T0_8BIT & // 8 bit T0_SOURCE_INT & // internal clock T0_PS_1_256); // 1/256 clock speed // Set A/D Channel; 0000=AN0, 0100=AN4 ADCON0bits.CHS3 = 0; ADCON0bits.CHS2 = 1; ADCON0bits.CHS1 = 0; ADCON0bits.CHS0 = 0; // Set VREF; 00=VSS,VDD ADCON1bits.VCFG1 = 0; //Negative Voltage Reference ADCON1bits.VCFG0 = 1; //Positive Voltage Reference // Set A/D Result Format; 1=right just ADCON2bits.ADFM = 1; // Set A/D Conv clock; 010=32TOSC; 110=64TOSC ADCON2bits.ADCS2 = 0; ADCON2bits.ADCS1 = 1; ADCON2bits.ADCS0 = 0; // Set A/D TAD; 001=2TAD ADCON2bits.ACQT2 = 0; ADCON2bits.ACQT1 = 0; ADCON2bits.ACQT0 = 1; //Turn on AD ADCON0bits.ADON = 1; INTCONbits.GIE=1; // needed to make timer interrupt catch ConvertADC(); // Start conversion (preps for first read) WriteTimer0(0); // sets PreLoad}
//void SetOutputs(unsigned char numOuts,// unsigned char outVals[],// volatile near unsigned char * outPorts[], // unsigned char outBits[]) {// function to set outputs with outVals array rather than explicitly// keeping track of port/bit configurations// written by Sean Montgomery, 2008.08void SetOutputs(unsigned char numOuts, unsigned char outVals[], volatile near unsigned char * outPorts[], unsigned char outBits[]) { unsigned char j;// for (j=0;j<(sizeof(outVals)/sizeof(outVals[0]));j++) { for (j=0;j<numOuts;j++) { if (outVals[j]) { *outPorts[j] = ((*outPorts[j]) | outBits[j]); } else { *outPorts[j] = ((*outPorts[j]) & (0b11111111 - outBits[j])); } }}
extern void SetOutputs(unsigned char numOuts, unsigned char outVals[], volatile near unsigned char * outPorts[], unsigned char outBits[]);