📄 clnnm.nc
字号:
/* CLNN implmentation *//* Written by Tatiana Bokareva, Kin Sun Ho (tbokareva,ksho@cse) *//* Last Modified: 09 September 2005 */includes Sasha;module CLNNM{ provides interface CLNNlib; provides interface StdControl; uses { interface Timer; interface Leds; interface Anycastlib; interface StdControl as SensorControl; interface StdControl as CommControl; interface ADC as Sensor; }}implementation{ uint8_t reading; // raw reading taken to fill buffer <= buffer uint8_t training; // number of training done uint16_t buffer[NUM_UNITS]; // buffer to store raw sensor data struct clnn *ptnn; // neural network structure uint16_t epocht = -1; // current epoch uint16_t verify; // verify or training struct Anycast *vdata; // storing the content of verify broadcast uint16_t num_verify; // num of verify uint16_t verify_fault; // number of fault discovered uint16_t c_min; // current verify min uint16_t c_max; // current verify max /* The following print statement is for debugging in tossim To run the program in tossim: # make pc # export DBG=usr1 # ./build/pc/main.exe 1 */ /* prints raw sensor data received */ void print_raw() { uint8_t i=0; dbg(DBG_USR1, "Input Vector: "); for(i=0; i<NUM_UNITS; i++) { dbg(DBG_USR1, "%d ", buffer[i]); } dbg(DBG_USR1, "\n"); } /* prints the weight matrix which is used for training */ void print_weights(){ uint8_t i=0; uint8_t j=0; for(i=0; i<NUM_UNITS; i++){ atomic { dbg(DBG_USR1, "WEIGHTS: %u - ", i); } for(j=0; j< NUM_UNITS; j++){ dbg(DBG_USR1, "%u ", ptnn->weights[i][j]); } dbg(DBG_USR1, "\n"); } } /* prints the clusters */ void print_clusters() { uint8_t i=0; for(i=0; i<NUM_UNITS; i++){ dbg(DBG_USR1, "CLUSTERS: %u %u %u %u\n", i, ptnn->clusters[i][0], ptnn->clusters[i][1],ptnn->clusters[i][2]); } } /* asks CLNN reset its weight matrix and all information it have */ command result_t CLNNlib.reset() { /* parameters to assign the weight array */ uint8_t i=0; uint8_t j=0; uint16_t step=100; uint8_t inc=100; dbg(DBG_USR1, "CLNN reinitialized\n"); atomic { reading = 0; training = 0; //initilise the weights and clusters for(i=0; i<NUM_UNITS; i++){ for(j=0; j< NUM_UNITS; j++){ ptnn->weights[i][j]=step; ptnn->clusters[i][0]=NEGDIST; ptnn->clusters[i][1]=NEGDIST; ptnn->clusters[i][2]=0; } step=step+inc; } } print_weights(); return SUCCESS; } // ask CLNN to start training command result_t CLNNlib.start_training() { verify = 0; return call Timer.start(TIMER_REPEAT,SENSOR_PERIOD); } // ask CLNN to start verify command result_t CLNNlib.start_verify(struct Anycast *pt) { atomic { verify = 1; vdata->min = pt->min; // stoare min/max values in vdata vdata->max = pt->max; // for use in ADC vdata->min1 = pt->min1; vdata->max1 = pt->max1; vdata->min2 = pt->min2; vdata->max2 = pt->max2; vdata->min3 = pt->min3; vdata->max3 = pt->max3; vdata->nintervals = pt->nintervals; num_verify = 0; verify_fault = 0; c_min = 0; c_max = 0; } return call Timer.start(TIMER_REPEAT,SENSOR_PERIOD); } /* Function to be called from Anycast to request for Marzullo intersection */ command result_t CLNNlib.request(Cluster_Msg *datat) { uint16_t trained; // number of times trained so far uint16_t values[NUM_UNITS]; //number of time units won uint16_t ind[NUM_UNITS]; //index of the clusters uint16_t tmp_v; uint16_t tmp_i; uint8_t i; uint8_t j; atomic { trained = training; } if(trained != MAX_TRAIN) return FAIL; for(i=0; i<NUM_UNITS; i++) { values[i]=ptnn->clusters[i][2]; ind[i]=i; } // sort the clusters based on the number of won competions for(i=0; i<NUM_UNITS-1; i++) { for(j=0; j<NUM_UNITS-1-i; j++) { if(values[j+1]>values[j]){/* compare the two neighbors */ tmp_v=values[j]; tmp_i=ind[j]; values[j]=values[j+1]; values[j+1]=tmp_v; ind[j]=ind[j+1]; ind[j+1]=tmp_i; } } } atomic { datat->win1 = ptnn->clusters[ind[0]][2]; // storing results datat->win2 = ptnn->clusters[ind[1]][2]; datat->win3 = ptnn->clusters[ind[2]][2]; // # of times win datat->win4 = ptnn->clusters[ind[3]][2]; datat->min1 = ptnn->clusters[ind[0]][0]; datat->min2 = ptnn->clusters[ind[1]][0]; datat->min3 = ptnn->clusters[ind[2]][0]; // minimum datat->min4 = ptnn->clusters[ind[3]][0]; datat->max1 = ptnn->clusters[ind[0]][1]; datat->max2 = ptnn->clusters[ind[1]][1]; datat->max3 = ptnn->clusters[ind[2]][1]; // maximum of each clusters datat->max4 = ptnn->clusters[ind[3]][1]; datat->train = training; // # of training } return SUCCESS; } /** * Used to initialize this component. */ command result_t StdControl.init() { /* parameters to assign the weight array */ uint8_t i=0; uint8_t j=0; uint16_t step=100; uint8_t inc=100; call Leds.init(); call SensorControl.init(); atomic { ptnn =(struct clnn*) malloc(sizeof(struct clnn)); vdata = (struct Anycast*) malloc(sizeof(struct Anycast)); reading = 0; training = 0; //initilise the weights and clusters for(i=0; i<NUM_UNITS; i++){ for(j=0; j< NUM_UNITS; j++){ ptnn->weights[i][j]=step; ptnn->clusters[i][0]=NEGDIST; ptnn->clusters[i][1]=NEGDIST; ptnn->clusters[i][2]=0; } step=step+inc; } } print_weights(); return SUCCESS; } /** * Starts the SensorControl and CommControl components. * @return Always returns SUCCESS. */ command result_t StdControl.start() { call SensorControl.start(); return SUCCESS; } /** * Stops the SensorControl and CommControl components. * @return Always returns SUCCESS. */ command result_t StdControl.stop() { call SensorControl.stop(); call Timer.stop(); return SUCCESS; } /* Trains raw sensor data with CLNN clustering */ void clnn_train() { /* varibles for indexing into arrays */ uint8_t i = 0; uint8_t j = 0; uint8_t k = 0; /* varibles for storing local temp values */ uint32_t temp = 0; uint32_t temp2 = 0; uint32_t sum = 0; uint16_t trained; /* minimum distance beween the winner and input vector */ uint32_t min_dist = NEGDIST; /* minimum distance beween the lossers and input vector */ uint32_t min_distL = NEGDIST; /* current training winner */ uint8_t winner = NEGDIST; /* number of current epochs trained */ uint8_t e=0; /* number of iterations done */ uint8_t iterations=0; /* Calculate the Euclidean distance from the input vector unit to all weights */ for(i=0; i<NUM_UNITS ;i++) { for(j=0; j<NUM_UNITS; j++) { temp = ptnn->weights[i][j] - buffer[j]; sum += temp*temp; } if(sum <= min_dist || min_dist == -1) { min_dist = sum; winner = i; } sum = 0; } print_raw(); // for debug atomic { /* Update the winning cluster interval and the number of won times */ if(ptnn->clusters[winner][2] == 0) { ptnn->clusters[winner][0] = ptnn->clusters[winner][1] = buffer[0]; } ptnn->clusters[winner][2]++; } for(i=0;i<NUM_UNITS;i++){ atomic { if(buffer[i] < ptnn->clusters[winner][0]){ ptnn->clusters[winner][0]= buffer[i]; } if(buffer[i] > ptnn->clusters[winner][1]){ ptnn->clusters[winner][1]= buffer[i]; } } } dbg(DBG_USR1, "(%d,%d,%d)\n", ptnn->clusters[winner][0], ptnn->clusters[winner][1],ptnn->clusters[winner][2]); /* Update the weights of the winner and perform the leaky learning on other neurons. Do that until one of the following has happend: 1) reach maximum number of EPOCHS 2) the distance between the weight and the input vector Cannot be improved anymore. This is due to the resolution of the division operator on modes. I.e no floating points division :( */ for(e=0; e<MAX_EPOCH; e++){ sum = 0; for(i=0; i<NUM_UNITS; i++) { if(i == winner) { for(j=0;j<NUM_UNITS;j++) { atomic { temp2 = (buffer[j]- ptnn->weights[winner][j]) >> 3; ptnn->weights[winner][j] += temp2; } } /* Calculate the new distance between the input and the weight vector*/ sum = 0; for(k=0;k<NUM_UNITS;k++){ atomic { temp = ptnn->weights[winner][k] - buffer[k]; } sum += temp*temp; } /* the distance between the weight and the vector cannot be improved anymore. I.e previous distance = currently calculated */ sum = sqrt(sum); if(min_dist == sum) { //call Leds.redOn(); iterations = e; e = MAX_EPOCH; } else{ min_dist = sum; } } else { for(j =0; j<NUM_UNITS;j++) { atomic { temp2 = (buffer[j]-ptnn->weights[i][j]) >> 8; ptnn->weights[i][j] += temp2; } sum = 0; for(k=0;k<NUM_UNITS;k++){ atomic { temp = ptnn->weights[j][k] - buffer[k]; } sum += temp*temp; } sum = sqrt(sum); /* the distance between the weight and the input vector can not be improuved anymore. I.e previous distance = currently calculated */ if(min_distL == sum) { //call Leds.redOn(); continue; } else{ min_distL = sum; } } } } } atomic { // update the training count trained = ++training; call Leds.yellowToggle(); dbg(DBG_USR1, "Training number %d finished with %d interations\n", trained, iterations); print_raw(); print_weights(); print_clusters(); } if(trained < MAX_TRAIN) call Timer.start(TIMER_REPEAT,SENSOR_PERIOD); if(trained == MAX_TRAIN) { call Leds.greenOn(); call Leds.yellowOn(); call Anycastlib.start_timer(); } } /** * Signalled when data is ready from the ADC. Stuffs the sensor * reading into the current packet, and call train task when * BUFFER_SIZE readings have been taken. * @return Always returns SUCCESS. */ async event result_t Sensor.dataReady(uint16_t data) { uint16_t trained; uint16_t Nfinals; uint8_t is_fault = 1; Nfinals = vdata->nintervals; // do Verify ADC operation if(verify == 1) { atomic { num_verify++; // increment # of verify count //[tb] Send packet every 1000 readings. if(num_verify >= 1000) { call Timer.stop(); /* [KS] Include buffer ADC */ call Anycastlib.start_verify(verify_fault,c_min,c_max,buffer); } // put data into buffer /* [KS] Include buffer ADC */ buffer[reading++] = data; // store data into the buffer if(reading == NUM_UNITS) { reading = 0; } // check for each intervals if(Nfinals >= 1) { if(data <= vdata->max && data >= vdata->min) { is_fault = 0; } } if(Nfinals >= 2) { if(data <= vdata->max1 && data >= vdata->min1) { is_fault = 0; } } if(Nfinals >= 3) { if(data <= vdata->max2 && data >= vdata->min2) { is_fault = 0; } } if(Nfinals >= 4) { if(data <= vdata->max3 && data >= vdata->min3) { is_fault = 0; } } // if there is a fault, increase the fault count if(is_fault == 1) { call Leds.greenToggle(); verify_fault++; // if the min/max count haven't been set before if(c_min == 0 && c_max == 0) { c_min = data; c_max = 0; } if(data < c_min) c_min = data; if(data > c_max) c_max = data; } // else decrease the fault count if > 0 else { call Leds.redToggle(); if(verify_fault > 0) verify_fault--; } // Enable the lines for immediate sending of fault if > MAX_FAULTS /* //[tb] MAXIMUM FAULTS reached the threshold. Send falty notification if(verify_fault >= MAX_FAULTS) { call Timer.stop(); // [KS] Include buffer ADC call Anycastlib.start_verify(verify_fault,c_min,c_max,buffer); } */ } return SUCCESS; } /////// // below is for CLNN training operation ////// atomic { trained = training; } // check if we have reached MAX_TRAIN if(trained >= MAX_TRAIN) { call Timer.stop(); return SUCCESS; } atomic { buffer[reading++] = data; // store data into the buffer call Leds.greenToggle(); if(reading == NUM_UNITS) { reading = 0; call Timer.stop(); // stop the timer during training clnn_train(); // if bbuffer is full do a clnn training } } return SUCCESS; } /** * Signalled when the clock ticks. * @return The result of calling Photo.getData(). */ event result_t Timer.fired() { return call Sensor.getData(); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -