Marc Bax
/
EtonBreadboard_091
Modification in routine to select substance
Embed:
(wiki syntax)
Show/hide line numbers
main.cpp
00001 //Firmware to drive Eton bee trainer breadboard 00002 char* fwversion = "0.91"; //For published versions use format "n.nn" 00003 //For development versions add "D" to end of string 00004 //This version published on 31/03/2011 00005 00006 //Include libraries 00007 #include "mbed.h" 00008 #include "Servo.h" //need this library to control servos 00009 00010 //Pin assignments and external functions 00011 DigitalOut led1(LED1), led2(LED2), led3(LED3), led4(LED4); //for debugging purposes only 00012 DigitalOut buzzer(p5); //pin high means buzzer on 00013 DigitalOut airswitcher(p7); //pin high shorts coax for air switcher valve 00014 Serial display(p9,p10); //serial display controller by ByVAC BV4618 controller 00015 AnalogOut irLED(p18); //only one analog out controls both IR LEDS in parallel 00016 AnalogIn ptor1(p19), ptor2(p20); //analog input for beeholder phototransistors 00017 Servo arm1(p21), elbow1(p22); //servos for station 1 robot arm 00018 Servo arm2(p23), elbow2(p24); //servos for station 2 robot arm 00019 I2C beeholder(p28,p27); //set up I2C communication to read beeholder serial no 00020 DigitalOut bhsel1(p29), bhsel2(p30); //select lines for station 1 and station 2 - pull low to select holder 00021 DigitalIn upsw(p13), risw(p14), dnsw(p15), lesw(p16), oksw(p17); //footswitch connected parallel to OK switch 00022 LocalFileSystem local("local"); //allow access to the mbed "thumbdrive" as a file system 00023 FILE *logfile = fopen("/local/etonlog.csv","w"); //creates new file etonlog.csv and set for writing. Overwrites existing file! 00024 00025 //Definition of global constants 00026 //station 1 (left) robot arm positions 00027 float arm1basepos = 0.4; 00028 float elbow1basepos = 0.07; 00029 float arm1dippos = 0.2; 00030 float elbow1dippos = 0.6; 00031 float arm1ticklepos = 0.65; 00032 float elbow1ticklepos = 0.07; 00033 float arm1feedpos = 0.7; 00034 float elbow1feedpos = 0.4; 00035 00036 //station 2 (right) robot arm positions 00037 float arm2basepos = 0.4; 00038 float elbow2basepos = 0.07; 00039 float arm2dippos = 0.2; 00040 float elbow2dippos = 0.07; 00041 float arm2ticklepos = 0.2; 00042 float elbow2ticklepos = 0.07; 00043 float arm2feedpos = 0.2; 00044 float elbow2feedpos = 0.07; 00045 00046 //robot arm hold and move times all times are in seconds 00047 float diptime = 1; //time that brush stays down dipped in sugar water 00048 float tickletimeout = 3; //maximum time to tickle if no PER is detected 00049 float feedtime = 3; //feeding time 00050 00051 //PER detection parameters 00052 float calsetval = 1.4; //voltage to which phototransistor output will be calibrated 00053 float PERsetval = 2.1; //phototransistor output needs to be above this voltage for PER 00054 float PERtime = 0.2; //phototransistor output needs to stay high this long in seconds 00055 00056 //I2C address 00057 int addr = 0xA2; //address is actually 0x51, but mbed expects left-shifted address 00058 00059 //Definition of global variables 00060 00061 struct holderrecord { //used to hold data on beeholder 00062 int serialno; //beeholder serial number 0-9999 00063 float calvalue; //IR-LED calibration value 00064 char cycleno; //number of cycles gone through in this session 00065 char reslastcycle; //result of last cycle, 1 for PER 00066 char ticklenextcycle; //whether tickling was done for last cycle 00067 time_t tstamp; //timestamp when last cycle was run 00068 }; 00069 00070 holderrecord currentholder; //struct record for the current beeholder 00071 holderrecord sessionrecord[30]; //sessionrecord contains holderrecords for up to 30 beeholders 00072 00073 int numbeeholders; //number of beeholders used in current session 00074 int station; //which station is used in this session 00075 00076 //Substance strings 00077 00078 struct submenuitem { 00079 char* displaystring; //keep display string to 19 characters or less, otherwise display screws up 00080 char* logstring; //this is the string that gets printed in the logfile, and can be longer then 19 characters 00081 }; 00082 00083 submenuitem submenu[11]; 00084 int substanceindex; //this variable contains the index number (in the list) of the selected substance 00085 00086 //Function declarations 00087 00088 //Short beep 00089 void beeponce() { 00090 buzzer = 1; 00091 wait(0.1); 00092 buzzer = 0; 00093 } 00094 00095 //beep beep beep 00096 void multibeeps(int number, float interval) { 00097 for(int i=0;i<number;i++){ 00098 beeponce(); 00099 wait(interval); 00100 } 00101 } 00102 00103 //Clears and homes the display 00104 void cleardisplay() { 00105 display.printf("\e[2J\e[H"); 00106 } 00107 00108 //Returns both robot arms to base position 00109 void armstobase() { 00110 elbow1 = elbow1basepos; 00111 elbow2 = elbow2basepos; 00112 wait(0.5); //need this delay to avoid snagging brush on IR LED 00113 arm1 = arm1basepos; 00114 arm2 = arm2basepos; 00115 } 00116 00117 //Fills the substance menu array with text 00118 void fillsubstancemenu() { 00119 submenu[0].displaystring = "No substance"; 00120 submenu[0].logstring = "Lack of substance"; 00121 00122 submenu[1].displaystring = "Coffee"; 00123 submenu[1].logstring = "Espresso macchiato"; 00124 00125 submenu[2].displaystring = "Earl Grey"; 00126 submenu[2].logstring = "Nice cup of tea"; 00127 00128 submenu[3].displaystring = "Apple Pie"; 00129 submenu[3].logstring = "Mom's homemade apple pie - longer then 19 characters"; 00130 00131 submenu[4].displaystring = "Substance 04"; 00132 submenu[4].logstring = "Substance 4"; 00133 00134 submenu[5].displaystring = "Substance 05"; 00135 submenu[5].logstring = "Substance 5"; 00136 00137 submenu[6].displaystring = "Substance 06"; 00138 submenu[6].logstring = "Substance 6"; 00139 00140 submenu[7].displaystring = "Substance 07"; 00141 submenu[7].logstring = "Substance 7"; 00142 00143 submenu[8].displaystring = "Substance 08"; 00144 submenu[8].logstring = "Substance 8"; 00145 00146 submenu[9].displaystring = "Substance 09"; 00147 submenu[9].logstring = "Substance 9"; 00148 00149 submenu[10].displaystring = "Red Roses"; 00150 submenu[10].logstring = "I never promised you a rose garden"; 00151 } 00152 00153 //Initialises sessionrecords 00154 void sessionrecordinit() { 00155 for (int i=0; i<30; i++) { //set base values for all possible beeholders 00156 sessionrecord[i].serialno = 0; //set serialno to 0 so we can detect a unresponsive holder 00157 sessionrecord[i].calvalue = 0; 00158 sessionrecord[i].cycleno = 0; 00159 sessionrecord[i].reslastcycle = 0; 00160 sessionrecord[i].ticklenextcycle = 1; //default is to tickle on each cycle 00161 } 00162 } 00163 00164 //Initialisation on power-on 00165 void initialise() { 00166 00167 //Set pins to a defined state 00168 led1 = led2 = led3 = led4 =0; //internal LEDs only used for debugging purposes 00169 buzzer = 0; //buzzer off 00170 airswitcher = 0; //relay contacts open, clean air position 00171 bhsel1 = bhsel2 = 1; //I2C select lines high to deselect both beeholders 00172 upsw.mode(PullUp); //set pull-up on all frontpanel switches 00173 risw.mode(PullUp); 00174 dnsw.mode(PullUp); 00175 lesw.mode(PullUp); 00176 oksw.mode(PullUp); 00177 00178 //Set robot arms to base positions 00179 armstobase(); 00180 00181 //initialise the display 00182 display.baud(19200); //set display baud rate to 19200 00183 display.putc(0x0d); //send CR to display - this needs to be first character sent after power-up 00184 wait(0.5); //wait for display to adjust to serial baud rate 00185 display.printf("\e[4L\e[20c"); //set display to 4 lines of 20 characters 00186 cleardisplay(); //clear screen and home cursor 00187 00188 //display splash screen with time 00189 display.printf("Eton trainer v%s\r", fwversion); //show firmware release version 00190 time_t seconds = time(NULL); //creates timestamp 00191 char bufferd[20], buffert[20]; 00192 strftime(bufferd, 20, "%d/%m/%Y", localtime(&seconds)); //formats date part of timestamp 00193 display.printf("Date: %s\r", bufferd); //displays date 00194 strftime(buffert, 20, "%X", localtime(&seconds)); //formats time part of timestamp 00195 display.printf("Time: %s\r", buffert); //displays time 00196 wait(3); //display splash screen 00197 cleardisplay(); //clear screen and home cursor 00198 00199 //initialise sessionrecord 00200 sessionrecordinit(); 00201 00202 //initialise substance menu 00203 fillsubstancemenu(); 00204 00205 //enter info in logfile.csv 00206 fprintf(logfile, "%s\r", bufferd); //writes date, time and firmware version 00207 fprintf(logfile, "%s\r", buffert); 00208 fprintf(logfile, "v%s\r", fwversion); 00209 00210 beeponce(); //three beeps to signal initialisation ready 00211 } 00212 00213 //Returns the index of the selected substance menu item 00214 int subchoice(submenuitem submenu[11]) { 00215 bool up, down, done; 00216 int i; 00217 up = down = done = 0; 00218 i = 0; 00219 cleardisplay(); 00220 display.printf("Substance selection"); 00221 wait(3); 00222 cleardisplay(); 00223 while (!done) { 00224 display.printf("%s\r", submenu[i].displaystring); 00225 display.printf("\rUP/DOWN to scroll\rOK to select"); 00226 wait(1); //delay required to avoid very rapid cycling of the menu 00227 while (!up && !down && !done) { 00228 up = !upsw; 00229 down = !dnsw; 00230 done = !oksw; 00231 } 00232 if (down) { 00233 i++; 00234 if (i==11) i = 0; 00235 } 00236 if (up) { 00237 if (i==0) i = 11; 00238 i--; 00239 } 00240 cleardisplay(); 00241 } 00242 return i; 00243 } 00244 00245 //Converts the last 4 digits in the serial number string into a integer 0-9999 00246 int serialstring2int(char bser[8]) { 00247 int tempserial = 0; 00248 tempserial = tempserial + (bser[4]-0x30)*1000; //5th digit is thousands 00249 tempserial = tempserial + (bser[5]-0x30)*100; //6th digit is hundreds 00250 tempserial = tempserial + (bser[6]-0x30)*10; //7th digit is tens 00251 tempserial = tempserial + (bser[7]-0x30); //8th digit is units 00252 return tempserial; 00253 } 00254 00255 //beeholder resets on rising edge of select line 00256 void resetbeeholder() { //need this as mounting beeholder causes undefined start of beeholder firmware 00257 bhsel1 = bhsel2 = 0; 00258 wait(0.1); 00259 bhsel1 = bhsel2 = 1; 00260 wait(0.3); 00261 } 00262 00263 //Reads beeholder serial number from station 1 or 2 00264 int getserialno(int station) { 00265 char bser[8]; //define 8-byte serial number string to read 00266 resetbeeholder(); //does not work without this!! 00267 for (int i=0;i<8;i++) bser[i]=0x30; 00268 if (station==1) bhsel1=0; //pull select line station 1 low 00269 if (station==2) bhsel2=0; //pull select line station 2 low 00270 wait(0.2); 00271 beeholder.stop(); //I2C stop condition 00272 wait(0.2); //delay for beeholder to respond 00273 beeholder.write(addr,0x0,1); //initial write before read 00274 beeholder.read(addr,bser,8); //read 8 byte serial number 00275 bhsel1 = bhsel2= 1; //pull both select lines high 00276 int serialno = serialstring2int(bser); //translate serial number string to integer 00277 return serialno; 00278 } 00279 00280 //Returns 1 if a PER is detected on this beeholder within timeout seconds 00281 int detectPER(int station, float timeout) { 00282 Timer ttotal, tper; 00283 ttotal.start(); //start timers for time-out and PER-detect 00284 ttotal.reset(); 00285 tper.start(); 00286 tper.reset(); 00287 if (station == 1) { 00288 while ((ttotal.read() < timeout) && (tper.read() < PERtime)) { //loop until timeout or PER detected 00289 wait_ms(10); 00290 if (ptor1 * 3.3 < PERsetval) tper.reset(); //if phototransistor voltage below treshold keep PER timer in reset 00291 //if above treshold let timer run until it reaches PERtime 00292 } 00293 } 00294 if (station == 2) { 00295 while ((ttotal.read() < timeout) && (tper.read() < PERtime)) { 00296 if (ptor2 * 3.3 < PERsetval) tper.reset(); 00297 } 00298 } 00299 ttotal.stop(); 00300 tper.stop(); 00301 return (tper.read() >= PERtime); //if the loop exit condition was a PER, return a TRUE value 00302 } 00303 00304 //Checks if bee shows PER when stimulated with odour but without feeding 00305 int checktrained(int station) { 00306 airswitcher = 1; 00307 int responded = detectPER(station, 6); //PER needs to be detected within 6 seconds 00308 airswitcher = 0; 00309 return responded; 00310 } 00311 00312 //Function performs beeholder/IR-led calibration 00313 float calibrate(int station, int runs) { 00314 float tempcal; 00315 tempcal=0.5; //start calibration at 50% voltage 00316 irLED=tempcal; 00317 float calstep; //start calstep at 25% voltage 00318 calstep = tempcal/2; 00319 for (int i=0; i<10; i++) { //does a "10-bit binary search" for the correct voltage to get a good response 00320 irLED = tempcal; 00321 wait(0.1); //important to allow AD converter to settle 00322 if (ptor1 < calsetval/3.3) { //check phototransistor voltage against desired value 00323 tempcal = tempcal - calstep; //if phototransistor voltage is too low then reduce brightness 00324 } 00325 else { 00326 tempcal = tempcal + calstep; //if phototransistor voltage is too high then increase brightness 00327 } 00328 calstep = calstep/2; //on each loop of the for-cycle make smaller changes to IR LED voltage 00329 } 00330 float calib; 00331 calib = tempcal; //set preliminary calibration to the value just measured 00332 for (int j=1; j<runs; j++) { //run another j-1 runs, this corrects for antennae-movement as 00333 tempcal=0.5; //we use the lowest calibration value from j runs 00334 irLED=tempcal; //this is similar to what we do in the cassettes 00335 calstep = tempcal/2; 00336 for (int i=0;i<10;i++) { 00337 irLED = tempcal; 00338 wait(0.1); 00339 if (ptor1 < calsetval/3.3) { 00340 tempcal = tempcal - calstep; 00341 } 00342 else { 00343 tempcal = tempcal + calstep; 00344 } 00345 calstep = calstep/2; 00346 } 00347 if (tempcal < calib) calib = tempcal; //use the lowest of j calibration values 00348 } 00349 return calib; 00350 } 00351 00352 //switches the IR LED on at the right brightness level for the beeholder 00353 void IRledON(int i) { 00354 irLED = sessionrecord[i].calvalue; 00355 } 00356 00357 //moves arm1 to a position in a specified time, allowing speed control 00358 void arm1move (float endpos, float movetime) { 00359 float startpos = arm1.read(); 00360 int numsteps = (movetime * 50); //50 pulses/second, so each step is 1 servo pulse 00361 for (int i=0; i<numsteps; i++) { 00362 arm1 = startpos + i * (endpos - startpos)/numsteps; 00363 wait(movetime/numsteps); 00364 } 00365 arm1 = endpos; 00366 } 00367 00368 //moves arm2 to a position in a specified time, allowing speed control 00369 void arm2move (float endpos, float movetime) { 00370 float startpos = arm2.read(); 00371 int numsteps = (movetime * 50); //50 pulses/second, so each step is 1 servo pulse 00372 for (int i=0; i<numsteps; i++) { 00373 arm2 = startpos + i * (endpos - startpos)/numsteps; 00374 wait(movetime/numsteps); 00375 } 00376 arm2 = endpos; 00377 } 00378 00379 //moves elbow1 to a position in a specified time, allowing speed control 00380 void elbow1move (float endpos, float movetime) { 00381 float startpos = elbow1.read(); 00382 int numsteps = (movetime * 50); //50 pulses/second, so each step is 1 servo pulse 00383 for (int i=0; i<numsteps; i++) { 00384 elbow1 = startpos + i * (endpos - startpos)/numsteps; 00385 wait(movetime/numsteps); 00386 } 00387 elbow1 = endpos; 00388 } 00389 00390 //moves elbow2 to a position in a specified time, allowing speed control 00391 void elbow2move (float endpos, float movetime) { 00392 float startpos = elbow2.read(); 00393 int numsteps = (movetime * 50); //50 pulses/second, so each step is 1 servo pulse 00394 for (int i=0; i<numsteps; i++) { 00395 elbow2 = startpos + i * (endpos - startpos)/numsteps; 00396 wait(movetime/numsteps); 00397 } 00398 elbow2 = endpos; 00399 } 00400 00401 //Performs a conditioning cycle. if tickle==0, no tickling takes place. Return==1 if a PER has been detected 00402 int condcycle(int station, int tickle) { 00403 int perseen; 00404 perseen = 0; 00405 //for station 1 00406 if (station == 1) { 00407 //dip brush 00408 arm1move(arm1dippos, 0.5); 00409 elbow1move(elbow1dippos, 0.3); 00410 wait(diptime); 00411 elbow1move(elbow1basepos, 0.3); 00412 arm1move(arm1basepos, 0.5); 00413 //switch air to supply trace vapour 00414 airswitcher = 1; //air contains target vapour 00415 display.printf("Vapour ON"); 00416 wait (0.5); 00417 //tickle 00418 if (tickle) { //if tickling, first tickle then wait for PER or timeout 00419 elbow1move(elbow1ticklepos, 0.2); 00420 arm1move(arm1ticklepos, 1.5); //slower move of arm towards bee 00421 perseen = detectPER(1, tickletimeout); //tickle until timeout or PER detected 00422 } 00423 //or not tickle 00424 else { 00425 perseen = detectPER(1, tickletimeout); //if not tickling, wait for PER or timeout then move to pre-feeding position 00426 arm1move(arm1ticklepos-0.05, 1); //move to position between LED and holder 00427 elbow1move(elbow1ticklepos, 0.3); 00428 } 00429 //feeding only if you have tickled or a PER has been detected 00430 if (tickle || perseen) { //only feed if a PER has been detector, or "tickle" is true 00431 elbow1move(elbow1feedpos, 0.3); 00432 arm1move(arm1feedpos, 0.3); 00433 wait(feedtime); 00434 arm1move(arm1ticklepos -0.05, 0.3); 00435 elbow1move(elbow1ticklepos, 0.3); 00436 } 00437 //move back to base position 00438 arm1 = arm1basepos; //use fast move here 00439 elbow1 = elbow1basepos; //use fast move here 00440 airswitcher = 0; //air valve to clean air 00441 display.printf("\e[DFF\r"); //rewrite "ON" to "OFF" on display 00442 } 00443 //for station 2 00444 if (station == 2) { 00445 //dip brush 00446 arm2move(arm2dippos, 0.5); 00447 elbow2move(elbow2dippos, 0.3); 00448 wait(diptime); 00449 elbow2move(elbow2basepos, 0.3); 00450 arm2move(arm2basepos, 0.5); 00451 //switch air to supply trace vapour 00452 //airswitcher = 1; //no air switching for station 2 00453 wait (0.5); 00454 //tickle 00455 if (tickle) { //if tickling, first tickle then wait for PER or timeout 00456 elbow2move(elbow2ticklepos, 0.2); 00457 arm2move(arm2ticklepos, 1.5); //slower move of arm towards bee 00458 perseen = detectPER(1, tickletimeout); //tickle until timeout or PER detected 00459 } 00460 //or not tickle 00461 else { 00462 perseen = detectPER(1, tickletimeout); //if not tickling, wait for PER or timeout then move to pre-feeding position 00463 arm2move(arm2ticklepos-0.05, 1); //move to position between LED and holder 00464 elbow2move(elbow2ticklepos, 0.3); 00465 } 00466 //feeding only if you have tickled or a PER has been detected 00467 if (tickle || perseen) { //only feed if a PER has been detector, or "tickle" is true 00468 elbow2move(elbow2feedpos, 0.3); 00469 arm2move(arm2feedpos, 0.3); 00470 wait(feedtime); 00471 arm2move(arm2ticklepos -0.05, 0.3); 00472 elbow2move(elbow2ticklepos, 0.3); 00473 } 00474 //move back to base position 00475 arm2 = arm2basepos; 00476 elbow2 = elbow2basepos; 00477 } 00478 return perseen; 00479 } 00480 00481 //User to input choice between station 1 and 2 for this session 00482 int stationchoice() { 00483 int station; 00484 station = 1; 00485 cleardisplay(); //clear screen and home cursor 00486 display.printf(" Station selection "); 00487 display.printf("Left=1 2=Right"); 00488 while (lesw && risw) { //lesw and risw become false when pressed! 00489 wait(0.02); 00490 if (!lesw) station=1; //on LEFT select station 1 00491 if (!risw) station=2; //on RIGHT select station 2 00492 } 00493 display.printf("\rStation %1u selected", station); 00494 fprintf(logfile, "%3u, station selected\r", station); 00495 return station; 00496 } 00497 00498 //Registers and calibrates all beeholders used in this session 00499 int registerbeeholders() { 00500 int i; 00501 bool done; 00502 char buffert[30]; 00503 i = done = 0; 00504 cleardisplay(); //clear screen and home cursor 00505 fprintf(logfile, "calibration record:\r"); 00506 fprintf(logfile, "i, serialno, LED V, time\r"); 00507 while (i<30 && !done) { //register and calibrate a maximum of 30 beeholders 00508 display.printf("calibrating %u\r",i+1); 00509 sessionrecord[i].serialno = getserialno(station); //read serial number 00510 if (sessionrecord[i].serialno != 0) { //check if serial number correctly read - if not it will be 0000 00511 sessionrecord[i].calvalue = calibrate(station, 5); //5 calibration cycles 00512 if ((sessionrecord[i].calvalue > 0.25) && (sessionrecord[i].calvalue < 0.97)) { //check that calvalue is in expected range 00513 sessionrecord[i].tstamp = time(NULL); //create timestamp NOW 00514 strftime(buffert, 20, "%X", localtime(&sessionrecord[i].tstamp)); //formats time part of timestamp 00515 cleardisplay(); 00516 display.printf("SN %4u - cal %4.2fV\r", sessionrecord[i].serialno, sessionrecord[i].calvalue*3.3); 00517 display.printf("OK for next\r"); 00518 display.printf("DOWN for training"); 00519 fprintf(logfile, "%4u,%6u,%6.2f, %s, calibrated\r", i, sessionrecord[i].serialno, sessionrecord[i].calvalue*3.3, buffert); 00520 i++; 00521 } 00522 else { 00523 cleardisplay(); 00524 display.printf("SN %4u - cal %4.2fV\r", sessionrecord[i].serialno, sessionrecord[i].calvalue*3.3); 00525 display.printf("Cal out of range!\r"); 00526 multibeeps(2,0.5); 00527 display.printf("OK to recalibrate\r"); 00528 fprintf(logfile, "%4u,%6u,%6.2f, %s, out of range\r", i, sessionrecord[i].serialno, sessionrecord[i].calvalue*3.3, buffert); 00529 } 00530 while (!done && oksw) { //loop until OK or DOWN are pressed 00531 wait(0.02); 00532 done = !dnsw; //DOWN exits registration cycle and moves to training 00533 } 00534 } 00535 else { //retry when serialno can't be read (is 0000) 00536 cleardisplay(); 00537 multibeeps(3,0.3); //beep-beep-beep when beeholder not correctly read 00538 display.printf("invalid serial no\r"); 00539 display.printf("reseat beeholder\r"); 00540 display.printf("press OK"); 00541 while (oksw) wait(0.02); //loop until OK is pressed to start calibration loop again 00542 } 00543 cleardisplay(); 00544 } 00545 return i; //upon done condition, i== number of beeholders calibrated 00546 } 00547 00548 //gets holderrecord for the holder with a certain serial number 00549 int getholderindex(int serialno) { 00550 for (int i=0; i<numbeeholders; i++) { //reverse lookup of index for a certain serial number 00551 if (sessionrecord[i].serialno == serialno) return i; 00552 } 00553 return 29; //if the record is not found, returns i==29 00554 } 00555 00556 //all the elements making up a single training cycle with one beeholder 00557 void trainingcycle() { 00558 wait(0.2); 00559 time_t tstamp = time(NULL); //create timestamp NOW 00560 char buffert[30]; 00561 strftime(buffert, 20, "%X", localtime(&tstamp)); //format timestamp to time string 00562 bool invalidserial; 00563 invalidserial = 1; 00564 int serialno; 00565 serialno = 0; 00566 while (invalidserial) { //loop until a serial number is read correctly 00567 cleardisplay(); 00568 int serialno = getserialno(station); //read serial number 00569 invalidserial = (serialno == 0); //if the serialno is 0, then it's invalid 00570 if (invalidserial) { 00571 display.printf("Invalid serialno\rReseat holder\rUP to retry"); 00572 while (upsw) wait(0.02); //loop until UP switch is pressed 00573 } 00574 } 00575 int i = getholderindex(serialno); //get index i for serial number 00576 IRledON(i); //switch IR LED on at correct brightness 00577 sessionrecord[i].cycleno++; //increment cycle number for this beeholder 00578 cleardisplay(); 00579 display.printf("SN: %4u, cycle %u\r", serialno, sessionrecord[i].cycleno); 00580 sessionrecord[i].reslastcycle = condcycle(station, sessionrecord[i].ticklenextcycle); //do a conditioning cycle 00581 fprintf(logfile, "%s,",buffert); 00582 fprintf(logfile, " %4u,",serialno); 00583 fprintf(logfile, " %2u,", sessionrecord[i].cycleno); 00584 if (sessionrecord[i].reslastcycle) { //log PER or TimeOut 00585 fprintf(logfile, " PER,"); 00586 } 00587 else { 00588 fprintf(logfile, " TO,"); 00589 } 00590 fprintf(logfile, " training\r"); 00591 if (sessionrecord[i].reslastcycle) { 00592 display.printf("PER detected\r"); 00593 } 00594 else { 00595 display.printf("PER time-out\r"); 00596 } 00597 display.printf("mount holder + OK\r"); 00598 display.printf("DOWN to finish"); 00599 } 00600 00601 //main program 00602 int main() { 00603 initialise(); //initialise a new session 00604 00605 //Choose which station this session will use 00606 station = stationchoice (); //menu to let user select station 1 or 2 00607 cleardisplay(); 00608 00609 //Choose substance string 00610 substanceindex = subchoice(submenu); //menu to let use chose substance 00611 fprintf(logfile, "%s\r", submenu[substanceindex].logstring); //prints the substance log string to the logfile 00612 00613 //Register and calibrate beeholders used in this session 00614 display.printf("Now register holders\r"); 00615 display.printf("seat first holder\rpress OK\r"); 00616 while (oksw) wait(0.02); //loop so first beeholder can be mounted, then OK pressed 00617 numbeeholders = registerbeeholders(); 00618 display.printf("%2u holders entered\r", numbeeholders); 00619 wait(3); 00620 cleardisplay(); 00621 00622 //Conduct training 00623 display.printf("Start training cycle\r"); 00624 display.printf("mount holder + OK\r"); 00625 display.printf("DOWN to finish"); 00626 fprintf(logfile, "Training started\r"); 00627 fprintf(logfile, "time, serial, cycleno, result\r"); 00628 wait(1); 00629 InterruptIn oksw(p17); //redefine OK and footswitch as interrupts 00630 oksw.mode(PullUp); 00631 bool finishsession; 00632 finishsession = 0; 00633 oksw.fall(&trainingcycle); //call subroutine "trainingcycle" on OK/footswitch interrupt 00634 while (!finishsession) { //loop while servicing interrupts 00635 wait(0.02); 00636 finishsession = !dnsw; //until DOWN button is pressed, which exits to program close 00637 } 00638 00639 //Close logfile 00640 fprintf(logfile, "session closed"); 00641 fclose(logfile); //close logfile for reading 00642 cleardisplay(); 00643 display.printf("Session finished\r\rdownload etonlog.csvand rename"); 00644 }
Generated on Fri Jul 22 2022 10:48:18 by 1.7.2