Modification in routine to select substance

Dependencies:   mbed Servo

Committer:
marcbax
Date:
Thu Mar 31 07:14:17 2011 +0000
Revision:
0:73e3587b65ec
v0.91

Who changed what in which revision?

UserRevisionLine numberNew contents of line
marcbax 0:73e3587b65ec 1 //Firmware to drive Eton bee trainer breadboard
marcbax 0:73e3587b65ec 2 char* fwversion = "0.91"; //For published versions use format "n.nn"
marcbax 0:73e3587b65ec 3 //For development versions add "D" to end of string
marcbax 0:73e3587b65ec 4 //This version published on 31/03/2011
marcbax 0:73e3587b65ec 5
marcbax 0:73e3587b65ec 6 //Include libraries
marcbax 0:73e3587b65ec 7 #include "mbed.h"
marcbax 0:73e3587b65ec 8 #include "Servo.h" //need this library to control servos
marcbax 0:73e3587b65ec 9
marcbax 0:73e3587b65ec 10 //Pin assignments and external functions
marcbax 0:73e3587b65ec 11 DigitalOut led1(LED1), led2(LED2), led3(LED3), led4(LED4); //for debugging purposes only
marcbax 0:73e3587b65ec 12 DigitalOut buzzer(p5); //pin high means buzzer on
marcbax 0:73e3587b65ec 13 DigitalOut airswitcher(p7); //pin high shorts coax for air switcher valve
marcbax 0:73e3587b65ec 14 Serial display(p9,p10); //serial display controller by ByVAC BV4618 controller
marcbax 0:73e3587b65ec 15 AnalogOut irLED(p18); //only one analog out controls both IR LEDS in parallel
marcbax 0:73e3587b65ec 16 AnalogIn ptor1(p19), ptor2(p20); //analog input for beeholder phototransistors
marcbax 0:73e3587b65ec 17 Servo arm1(p21), elbow1(p22); //servos for station 1 robot arm
marcbax 0:73e3587b65ec 18 Servo arm2(p23), elbow2(p24); //servos for station 2 robot arm
marcbax 0:73e3587b65ec 19 I2C beeholder(p28,p27); //set up I2C communication to read beeholder serial no
marcbax 0:73e3587b65ec 20 DigitalOut bhsel1(p29), bhsel2(p30); //select lines for station 1 and station 2 - pull low to select holder
marcbax 0:73e3587b65ec 21 DigitalIn upsw(p13), risw(p14), dnsw(p15), lesw(p16), oksw(p17); //footswitch connected parallel to OK switch
marcbax 0:73e3587b65ec 22 LocalFileSystem local("local"); //allow access to the mbed "thumbdrive" as a file system
marcbax 0:73e3587b65ec 23 FILE *logfile = fopen("/local/etonlog.csv","w"); //creates new file etonlog.csv and set for writing. Overwrites existing file!
marcbax 0:73e3587b65ec 24
marcbax 0:73e3587b65ec 25 //Definition of global constants
marcbax 0:73e3587b65ec 26 //station 1 (left) robot arm positions
marcbax 0:73e3587b65ec 27 float arm1basepos = 0.4;
marcbax 0:73e3587b65ec 28 float elbow1basepos = 0.07;
marcbax 0:73e3587b65ec 29 float arm1dippos = 0.2;
marcbax 0:73e3587b65ec 30 float elbow1dippos = 0.6;
marcbax 0:73e3587b65ec 31 float arm1ticklepos = 0.65;
marcbax 0:73e3587b65ec 32 float elbow1ticklepos = 0.07;
marcbax 0:73e3587b65ec 33 float arm1feedpos = 0.7;
marcbax 0:73e3587b65ec 34 float elbow1feedpos = 0.4;
marcbax 0:73e3587b65ec 35
marcbax 0:73e3587b65ec 36 //station 2 (right) robot arm positions
marcbax 0:73e3587b65ec 37 float arm2basepos = 0.4;
marcbax 0:73e3587b65ec 38 float elbow2basepos = 0.07;
marcbax 0:73e3587b65ec 39 float arm2dippos = 0.2;
marcbax 0:73e3587b65ec 40 float elbow2dippos = 0.07;
marcbax 0:73e3587b65ec 41 float arm2ticklepos = 0.2;
marcbax 0:73e3587b65ec 42 float elbow2ticklepos = 0.07;
marcbax 0:73e3587b65ec 43 float arm2feedpos = 0.2;
marcbax 0:73e3587b65ec 44 float elbow2feedpos = 0.07;
marcbax 0:73e3587b65ec 45
marcbax 0:73e3587b65ec 46 //robot arm hold and move times all times are in seconds
marcbax 0:73e3587b65ec 47 float diptime = 1; //time that brush stays down dipped in sugar water
marcbax 0:73e3587b65ec 48 float tickletimeout = 3; //maximum time to tickle if no PER is detected
marcbax 0:73e3587b65ec 49 float feedtime = 3; //feeding time
marcbax 0:73e3587b65ec 50
marcbax 0:73e3587b65ec 51 //PER detection parameters
marcbax 0:73e3587b65ec 52 float calsetval = 1.4; //voltage to which phototransistor output will be calibrated
marcbax 0:73e3587b65ec 53 float PERsetval = 2.1; //phototransistor output needs to be above this voltage for PER
marcbax 0:73e3587b65ec 54 float PERtime = 0.2; //phototransistor output needs to stay high this long in seconds
marcbax 0:73e3587b65ec 55
marcbax 0:73e3587b65ec 56 //I2C address
marcbax 0:73e3587b65ec 57 int addr = 0xA2; //address is actually 0x51, but mbed expects left-shifted address
marcbax 0:73e3587b65ec 58
marcbax 0:73e3587b65ec 59 //Definition of global variables
marcbax 0:73e3587b65ec 60
marcbax 0:73e3587b65ec 61 struct holderrecord { //used to hold data on beeholder
marcbax 0:73e3587b65ec 62 int serialno; //beeholder serial number 0-9999
marcbax 0:73e3587b65ec 63 float calvalue; //IR-LED calibration value
marcbax 0:73e3587b65ec 64 char cycleno; //number of cycles gone through in this session
marcbax 0:73e3587b65ec 65 char reslastcycle; //result of last cycle, 1 for PER
marcbax 0:73e3587b65ec 66 char ticklenextcycle; //whether tickling was done for last cycle
marcbax 0:73e3587b65ec 67 time_t tstamp; //timestamp when last cycle was run
marcbax 0:73e3587b65ec 68 };
marcbax 0:73e3587b65ec 69
marcbax 0:73e3587b65ec 70 holderrecord currentholder; //struct record for the current beeholder
marcbax 0:73e3587b65ec 71 holderrecord sessionrecord[30]; //sessionrecord contains holderrecords for up to 30 beeholders
marcbax 0:73e3587b65ec 72
marcbax 0:73e3587b65ec 73 int numbeeholders; //number of beeholders used in current session
marcbax 0:73e3587b65ec 74 int station; //which station is used in this session
marcbax 0:73e3587b65ec 75
marcbax 0:73e3587b65ec 76 //Substance strings
marcbax 0:73e3587b65ec 77
marcbax 0:73e3587b65ec 78 struct submenuitem {
marcbax 0:73e3587b65ec 79 char* displaystring; //keep display string to 19 characters or less, otherwise display screws up
marcbax 0:73e3587b65ec 80 char* logstring; //this is the string that gets printed in the logfile, and can be longer then 19 characters
marcbax 0:73e3587b65ec 81 };
marcbax 0:73e3587b65ec 82
marcbax 0:73e3587b65ec 83 submenuitem submenu[11];
marcbax 0:73e3587b65ec 84 int substanceindex; //this variable contains the index number (in the list) of the selected substance
marcbax 0:73e3587b65ec 85
marcbax 0:73e3587b65ec 86 //Function declarations
marcbax 0:73e3587b65ec 87
marcbax 0:73e3587b65ec 88 //Short beep
marcbax 0:73e3587b65ec 89 void beeponce() {
marcbax 0:73e3587b65ec 90 buzzer = 1;
marcbax 0:73e3587b65ec 91 wait(0.1);
marcbax 0:73e3587b65ec 92 buzzer = 0;
marcbax 0:73e3587b65ec 93 }
marcbax 0:73e3587b65ec 94
marcbax 0:73e3587b65ec 95 //beep beep beep
marcbax 0:73e3587b65ec 96 void multibeeps(int number, float interval) {
marcbax 0:73e3587b65ec 97 for(int i=0;i<number;i++){
marcbax 0:73e3587b65ec 98 beeponce();
marcbax 0:73e3587b65ec 99 wait(interval);
marcbax 0:73e3587b65ec 100 }
marcbax 0:73e3587b65ec 101 }
marcbax 0:73e3587b65ec 102
marcbax 0:73e3587b65ec 103 //Clears and homes the display
marcbax 0:73e3587b65ec 104 void cleardisplay() {
marcbax 0:73e3587b65ec 105 display.printf("\e[2J\e[H");
marcbax 0:73e3587b65ec 106 }
marcbax 0:73e3587b65ec 107
marcbax 0:73e3587b65ec 108 //Returns both robot arms to base position
marcbax 0:73e3587b65ec 109 void armstobase() {
marcbax 0:73e3587b65ec 110 elbow1 = elbow1basepos;
marcbax 0:73e3587b65ec 111 elbow2 = elbow2basepos;
marcbax 0:73e3587b65ec 112 wait(0.5); //need this delay to avoid snagging brush on IR LED
marcbax 0:73e3587b65ec 113 arm1 = arm1basepos;
marcbax 0:73e3587b65ec 114 arm2 = arm2basepos;
marcbax 0:73e3587b65ec 115 }
marcbax 0:73e3587b65ec 116
marcbax 0:73e3587b65ec 117 //Fills the substance menu array with text
marcbax 0:73e3587b65ec 118 void fillsubstancemenu() {
marcbax 0:73e3587b65ec 119 submenu[0].displaystring = "No substance";
marcbax 0:73e3587b65ec 120 submenu[0].logstring = "Lack of substance";
marcbax 0:73e3587b65ec 121
marcbax 0:73e3587b65ec 122 submenu[1].displaystring = "Coffee";
marcbax 0:73e3587b65ec 123 submenu[1].logstring = "Espresso macchiato";
marcbax 0:73e3587b65ec 124
marcbax 0:73e3587b65ec 125 submenu[2].displaystring = "Earl Grey";
marcbax 0:73e3587b65ec 126 submenu[2].logstring = "Nice cup of tea";
marcbax 0:73e3587b65ec 127
marcbax 0:73e3587b65ec 128 submenu[3].displaystring = "Apple Pie";
marcbax 0:73e3587b65ec 129 submenu[3].logstring = "Mom's homemade apple pie - longer then 19 characters";
marcbax 0:73e3587b65ec 130
marcbax 0:73e3587b65ec 131 submenu[4].displaystring = "Substance 04";
marcbax 0:73e3587b65ec 132 submenu[4].logstring = "Substance 4";
marcbax 0:73e3587b65ec 133
marcbax 0:73e3587b65ec 134 submenu[5].displaystring = "Substance 05";
marcbax 0:73e3587b65ec 135 submenu[5].logstring = "Substance 5";
marcbax 0:73e3587b65ec 136
marcbax 0:73e3587b65ec 137 submenu[6].displaystring = "Substance 06";
marcbax 0:73e3587b65ec 138 submenu[6].logstring = "Substance 6";
marcbax 0:73e3587b65ec 139
marcbax 0:73e3587b65ec 140 submenu[7].displaystring = "Substance 07";
marcbax 0:73e3587b65ec 141 submenu[7].logstring = "Substance 7";
marcbax 0:73e3587b65ec 142
marcbax 0:73e3587b65ec 143 submenu[8].displaystring = "Substance 08";
marcbax 0:73e3587b65ec 144 submenu[8].logstring = "Substance 8";
marcbax 0:73e3587b65ec 145
marcbax 0:73e3587b65ec 146 submenu[9].displaystring = "Substance 09";
marcbax 0:73e3587b65ec 147 submenu[9].logstring = "Substance 9";
marcbax 0:73e3587b65ec 148
marcbax 0:73e3587b65ec 149 submenu[10].displaystring = "Red Roses";
marcbax 0:73e3587b65ec 150 submenu[10].logstring = "I never promised you a rose garden";
marcbax 0:73e3587b65ec 151 }
marcbax 0:73e3587b65ec 152
marcbax 0:73e3587b65ec 153 //Initialises sessionrecords
marcbax 0:73e3587b65ec 154 void sessionrecordinit() {
marcbax 0:73e3587b65ec 155 for (int i=0; i<30; i++) { //set base values for all possible beeholders
marcbax 0:73e3587b65ec 156 sessionrecord[i].serialno = 0; //set serialno to 0 so we can detect a unresponsive holder
marcbax 0:73e3587b65ec 157 sessionrecord[i].calvalue = 0;
marcbax 0:73e3587b65ec 158 sessionrecord[i].cycleno = 0;
marcbax 0:73e3587b65ec 159 sessionrecord[i].reslastcycle = 0;
marcbax 0:73e3587b65ec 160 sessionrecord[i].ticklenextcycle = 1; //default is to tickle on each cycle
marcbax 0:73e3587b65ec 161 }
marcbax 0:73e3587b65ec 162 }
marcbax 0:73e3587b65ec 163
marcbax 0:73e3587b65ec 164 //Initialisation on power-on
marcbax 0:73e3587b65ec 165 void initialise() {
marcbax 0:73e3587b65ec 166
marcbax 0:73e3587b65ec 167 //Set pins to a defined state
marcbax 0:73e3587b65ec 168 led1 = led2 = led3 = led4 =0; //internal LEDs only used for debugging purposes
marcbax 0:73e3587b65ec 169 buzzer = 0; //buzzer off
marcbax 0:73e3587b65ec 170 airswitcher = 0; //relay contacts open, clean air position
marcbax 0:73e3587b65ec 171 bhsel1 = bhsel2 = 1; //I2C select lines high to deselect both beeholders
marcbax 0:73e3587b65ec 172 upsw.mode(PullUp); //set pull-up on all frontpanel switches
marcbax 0:73e3587b65ec 173 risw.mode(PullUp);
marcbax 0:73e3587b65ec 174 dnsw.mode(PullUp);
marcbax 0:73e3587b65ec 175 lesw.mode(PullUp);
marcbax 0:73e3587b65ec 176 oksw.mode(PullUp);
marcbax 0:73e3587b65ec 177
marcbax 0:73e3587b65ec 178 //Set robot arms to base positions
marcbax 0:73e3587b65ec 179 armstobase();
marcbax 0:73e3587b65ec 180
marcbax 0:73e3587b65ec 181 //initialise the display
marcbax 0:73e3587b65ec 182 display.baud(19200); //set display baud rate to 19200
marcbax 0:73e3587b65ec 183 display.putc(0x0d); //send CR to display - this needs to be first character sent after power-up
marcbax 0:73e3587b65ec 184 wait(0.5); //wait for display to adjust to serial baud rate
marcbax 0:73e3587b65ec 185 display.printf("\e[4L\e[20c"); //set display to 4 lines of 20 characters
marcbax 0:73e3587b65ec 186 cleardisplay(); //clear screen and home cursor
marcbax 0:73e3587b65ec 187
marcbax 0:73e3587b65ec 188 //display splash screen with time
marcbax 0:73e3587b65ec 189 display.printf("Eton trainer v%s\r", fwversion); //show firmware release version
marcbax 0:73e3587b65ec 190 time_t seconds = time(NULL); //creates timestamp
marcbax 0:73e3587b65ec 191 char bufferd[20], buffert[20];
marcbax 0:73e3587b65ec 192 strftime(bufferd, 20, "%d/%m/%Y", localtime(&seconds)); //formats date part of timestamp
marcbax 0:73e3587b65ec 193 display.printf("Date: %s\r", bufferd); //displays date
marcbax 0:73e3587b65ec 194 strftime(buffert, 20, "%X", localtime(&seconds)); //formats time part of timestamp
marcbax 0:73e3587b65ec 195 display.printf("Time: %s\r", buffert); //displays time
marcbax 0:73e3587b65ec 196 wait(3); //display splash screen
marcbax 0:73e3587b65ec 197 cleardisplay(); //clear screen and home cursor
marcbax 0:73e3587b65ec 198
marcbax 0:73e3587b65ec 199 //initialise sessionrecord
marcbax 0:73e3587b65ec 200 sessionrecordinit();
marcbax 0:73e3587b65ec 201
marcbax 0:73e3587b65ec 202 //initialise substance menu
marcbax 0:73e3587b65ec 203 fillsubstancemenu();
marcbax 0:73e3587b65ec 204
marcbax 0:73e3587b65ec 205 //enter info in logfile.csv
marcbax 0:73e3587b65ec 206 fprintf(logfile, "%s\r", bufferd); //writes date, time and firmware version
marcbax 0:73e3587b65ec 207 fprintf(logfile, "%s\r", buffert);
marcbax 0:73e3587b65ec 208 fprintf(logfile, "v%s\r", fwversion);
marcbax 0:73e3587b65ec 209
marcbax 0:73e3587b65ec 210 beeponce(); //three beeps to signal initialisation ready
marcbax 0:73e3587b65ec 211 }
marcbax 0:73e3587b65ec 212
marcbax 0:73e3587b65ec 213 //Returns the index of the selected substance menu item
marcbax 0:73e3587b65ec 214 int subchoice(submenuitem submenu[11]) {
marcbax 0:73e3587b65ec 215 bool up, down, done;
marcbax 0:73e3587b65ec 216 int i;
marcbax 0:73e3587b65ec 217 up = down = done = 0;
marcbax 0:73e3587b65ec 218 i = 0;
marcbax 0:73e3587b65ec 219 cleardisplay();
marcbax 0:73e3587b65ec 220 display.printf("Substance selection");
marcbax 0:73e3587b65ec 221 wait(3);
marcbax 0:73e3587b65ec 222 cleardisplay();
marcbax 0:73e3587b65ec 223 while (!done) {
marcbax 0:73e3587b65ec 224 display.printf("%s\r", submenu[i].displaystring);
marcbax 0:73e3587b65ec 225 display.printf("\rUP/DOWN to scroll\rOK to select");
marcbax 0:73e3587b65ec 226 wait(1); //delay required to avoid very rapid cycling of the menu
marcbax 0:73e3587b65ec 227 while (!up && !down && !done) {
marcbax 0:73e3587b65ec 228 up = !upsw;
marcbax 0:73e3587b65ec 229 down = !dnsw;
marcbax 0:73e3587b65ec 230 done = !oksw;
marcbax 0:73e3587b65ec 231 }
marcbax 0:73e3587b65ec 232 if (down) {
marcbax 0:73e3587b65ec 233 i++;
marcbax 0:73e3587b65ec 234 if (i==11) i = 0;
marcbax 0:73e3587b65ec 235 }
marcbax 0:73e3587b65ec 236 if (up) {
marcbax 0:73e3587b65ec 237 if (i==0) i = 11;
marcbax 0:73e3587b65ec 238 i--;
marcbax 0:73e3587b65ec 239 }
marcbax 0:73e3587b65ec 240 cleardisplay();
marcbax 0:73e3587b65ec 241 }
marcbax 0:73e3587b65ec 242 return i;
marcbax 0:73e3587b65ec 243 }
marcbax 0:73e3587b65ec 244
marcbax 0:73e3587b65ec 245 //Converts the last 4 digits in the serial number string into a integer 0-9999
marcbax 0:73e3587b65ec 246 int serialstring2int(char bser[8]) {
marcbax 0:73e3587b65ec 247 int tempserial = 0;
marcbax 0:73e3587b65ec 248 tempserial = tempserial + (bser[4]-0x30)*1000; //5th digit is thousands
marcbax 0:73e3587b65ec 249 tempserial = tempserial + (bser[5]-0x30)*100; //6th digit is hundreds
marcbax 0:73e3587b65ec 250 tempserial = tempserial + (bser[6]-0x30)*10; //7th digit is tens
marcbax 0:73e3587b65ec 251 tempserial = tempserial + (bser[7]-0x30); //8th digit is units
marcbax 0:73e3587b65ec 252 return tempserial;
marcbax 0:73e3587b65ec 253 }
marcbax 0:73e3587b65ec 254
marcbax 0:73e3587b65ec 255 //beeholder resets on rising edge of select line
marcbax 0:73e3587b65ec 256 void resetbeeholder() { //need this as mounting beeholder causes undefined start of beeholder firmware
marcbax 0:73e3587b65ec 257 bhsel1 = bhsel2 = 0;
marcbax 0:73e3587b65ec 258 wait(0.1);
marcbax 0:73e3587b65ec 259 bhsel1 = bhsel2 = 1;
marcbax 0:73e3587b65ec 260 wait(0.3);
marcbax 0:73e3587b65ec 261 }
marcbax 0:73e3587b65ec 262
marcbax 0:73e3587b65ec 263 //Reads beeholder serial number from station 1 or 2
marcbax 0:73e3587b65ec 264 int getserialno(int station) {
marcbax 0:73e3587b65ec 265 char bser[8]; //define 8-byte serial number string to read
marcbax 0:73e3587b65ec 266 resetbeeholder(); //does not work without this!!
marcbax 0:73e3587b65ec 267 for (int i=0;i<8;i++) bser[i]=0x30;
marcbax 0:73e3587b65ec 268 if (station==1) bhsel1=0; //pull select line station 1 low
marcbax 0:73e3587b65ec 269 if (station==2) bhsel2=0; //pull select line station 2 low
marcbax 0:73e3587b65ec 270 wait(0.2);
marcbax 0:73e3587b65ec 271 beeholder.stop(); //I2C stop condition
marcbax 0:73e3587b65ec 272 wait(0.2); //delay for beeholder to respond
marcbax 0:73e3587b65ec 273 beeholder.write(addr,0x0,1); //initial write before read
marcbax 0:73e3587b65ec 274 beeholder.read(addr,bser,8); //read 8 byte serial number
marcbax 0:73e3587b65ec 275 bhsel1 = bhsel2= 1; //pull both select lines high
marcbax 0:73e3587b65ec 276 int serialno = serialstring2int(bser); //translate serial number string to integer
marcbax 0:73e3587b65ec 277 return serialno;
marcbax 0:73e3587b65ec 278 }
marcbax 0:73e3587b65ec 279
marcbax 0:73e3587b65ec 280 //Returns 1 if a PER is detected on this beeholder within timeout seconds
marcbax 0:73e3587b65ec 281 int detectPER(int station, float timeout) {
marcbax 0:73e3587b65ec 282 Timer ttotal, tper;
marcbax 0:73e3587b65ec 283 ttotal.start(); //start timers for time-out and PER-detect
marcbax 0:73e3587b65ec 284 ttotal.reset();
marcbax 0:73e3587b65ec 285 tper.start();
marcbax 0:73e3587b65ec 286 tper.reset();
marcbax 0:73e3587b65ec 287 if (station == 1) {
marcbax 0:73e3587b65ec 288 while ((ttotal.read() < timeout) && (tper.read() < PERtime)) { //loop until timeout or PER detected
marcbax 0:73e3587b65ec 289 wait_ms(10);
marcbax 0:73e3587b65ec 290 if (ptor1 * 3.3 < PERsetval) tper.reset(); //if phototransistor voltage below treshold keep PER timer in reset
marcbax 0:73e3587b65ec 291 //if above treshold let timer run until it reaches PERtime
marcbax 0:73e3587b65ec 292 }
marcbax 0:73e3587b65ec 293 }
marcbax 0:73e3587b65ec 294 if (station == 2) {
marcbax 0:73e3587b65ec 295 while ((ttotal.read() < timeout) && (tper.read() < PERtime)) {
marcbax 0:73e3587b65ec 296 if (ptor2 * 3.3 < PERsetval) tper.reset();
marcbax 0:73e3587b65ec 297 }
marcbax 0:73e3587b65ec 298 }
marcbax 0:73e3587b65ec 299 ttotal.stop();
marcbax 0:73e3587b65ec 300 tper.stop();
marcbax 0:73e3587b65ec 301 return (tper.read() >= PERtime); //if the loop exit condition was a PER, return a TRUE value
marcbax 0:73e3587b65ec 302 }
marcbax 0:73e3587b65ec 303
marcbax 0:73e3587b65ec 304 //Checks if bee shows PER when stimulated with odour but without feeding
marcbax 0:73e3587b65ec 305 int checktrained(int station) {
marcbax 0:73e3587b65ec 306 airswitcher = 1;
marcbax 0:73e3587b65ec 307 int responded = detectPER(station, 6); //PER needs to be detected within 6 seconds
marcbax 0:73e3587b65ec 308 airswitcher = 0;
marcbax 0:73e3587b65ec 309 return responded;
marcbax 0:73e3587b65ec 310 }
marcbax 0:73e3587b65ec 311
marcbax 0:73e3587b65ec 312 //Function performs beeholder/IR-led calibration
marcbax 0:73e3587b65ec 313 float calibrate(int station, int runs) {
marcbax 0:73e3587b65ec 314 float tempcal;
marcbax 0:73e3587b65ec 315 tempcal=0.5; //start calibration at 50% voltage
marcbax 0:73e3587b65ec 316 irLED=tempcal;
marcbax 0:73e3587b65ec 317 float calstep; //start calstep at 25% voltage
marcbax 0:73e3587b65ec 318 calstep = tempcal/2;
marcbax 0:73e3587b65ec 319 for (int i=0; i<10; i++) { //does a "10-bit binary search" for the correct voltage to get a good response
marcbax 0:73e3587b65ec 320 irLED = tempcal;
marcbax 0:73e3587b65ec 321 wait(0.1); //important to allow AD converter to settle
marcbax 0:73e3587b65ec 322 if (ptor1 < calsetval/3.3) { //check phototransistor voltage against desired value
marcbax 0:73e3587b65ec 323 tempcal = tempcal - calstep; //if phototransistor voltage is too low then reduce brightness
marcbax 0:73e3587b65ec 324 }
marcbax 0:73e3587b65ec 325 else {
marcbax 0:73e3587b65ec 326 tempcal = tempcal + calstep; //if phototransistor voltage is too high then increase brightness
marcbax 0:73e3587b65ec 327 }
marcbax 0:73e3587b65ec 328 calstep = calstep/2; //on each loop of the for-cycle make smaller changes to IR LED voltage
marcbax 0:73e3587b65ec 329 }
marcbax 0:73e3587b65ec 330 float calib;
marcbax 0:73e3587b65ec 331 calib = tempcal; //set preliminary calibration to the value just measured
marcbax 0:73e3587b65ec 332 for (int j=1; j<runs; j++) { //run another j-1 runs, this corrects for antennae-movement as
marcbax 0:73e3587b65ec 333 tempcal=0.5; //we use the lowest calibration value from j runs
marcbax 0:73e3587b65ec 334 irLED=tempcal; //this is similar to what we do in the cassettes
marcbax 0:73e3587b65ec 335 calstep = tempcal/2;
marcbax 0:73e3587b65ec 336 for (int i=0;i<10;i++) {
marcbax 0:73e3587b65ec 337 irLED = tempcal;
marcbax 0:73e3587b65ec 338 wait(0.1);
marcbax 0:73e3587b65ec 339 if (ptor1 < calsetval/3.3) {
marcbax 0:73e3587b65ec 340 tempcal = tempcal - calstep;
marcbax 0:73e3587b65ec 341 }
marcbax 0:73e3587b65ec 342 else {
marcbax 0:73e3587b65ec 343 tempcal = tempcal + calstep;
marcbax 0:73e3587b65ec 344 }
marcbax 0:73e3587b65ec 345 calstep = calstep/2;
marcbax 0:73e3587b65ec 346 }
marcbax 0:73e3587b65ec 347 if (tempcal < calib) calib = tempcal; //use the lowest of j calibration values
marcbax 0:73e3587b65ec 348 }
marcbax 0:73e3587b65ec 349 return calib;
marcbax 0:73e3587b65ec 350 }
marcbax 0:73e3587b65ec 351
marcbax 0:73e3587b65ec 352 //switches the IR LED on at the right brightness level for the beeholder
marcbax 0:73e3587b65ec 353 void IRledON(int i) {
marcbax 0:73e3587b65ec 354 irLED = sessionrecord[i].calvalue;
marcbax 0:73e3587b65ec 355 }
marcbax 0:73e3587b65ec 356
marcbax 0:73e3587b65ec 357 //moves arm1 to a position in a specified time, allowing speed control
marcbax 0:73e3587b65ec 358 void arm1move (float endpos, float movetime) {
marcbax 0:73e3587b65ec 359 float startpos = arm1.read();
marcbax 0:73e3587b65ec 360 int numsteps = (movetime * 50); //50 pulses/second, so each step is 1 servo pulse
marcbax 0:73e3587b65ec 361 for (int i=0; i<numsteps; i++) {
marcbax 0:73e3587b65ec 362 arm1 = startpos + i * (endpos - startpos)/numsteps;
marcbax 0:73e3587b65ec 363 wait(movetime/numsteps);
marcbax 0:73e3587b65ec 364 }
marcbax 0:73e3587b65ec 365 arm1 = endpos;
marcbax 0:73e3587b65ec 366 }
marcbax 0:73e3587b65ec 367
marcbax 0:73e3587b65ec 368 //moves arm2 to a position in a specified time, allowing speed control
marcbax 0:73e3587b65ec 369 void arm2move (float endpos, float movetime) {
marcbax 0:73e3587b65ec 370 float startpos = arm2.read();
marcbax 0:73e3587b65ec 371 int numsteps = (movetime * 50); //50 pulses/second, so each step is 1 servo pulse
marcbax 0:73e3587b65ec 372 for (int i=0; i<numsteps; i++) {
marcbax 0:73e3587b65ec 373 arm2 = startpos + i * (endpos - startpos)/numsteps;
marcbax 0:73e3587b65ec 374 wait(movetime/numsteps);
marcbax 0:73e3587b65ec 375 }
marcbax 0:73e3587b65ec 376 arm2 = endpos;
marcbax 0:73e3587b65ec 377 }
marcbax 0:73e3587b65ec 378
marcbax 0:73e3587b65ec 379 //moves elbow1 to a position in a specified time, allowing speed control
marcbax 0:73e3587b65ec 380 void elbow1move (float endpos, float movetime) {
marcbax 0:73e3587b65ec 381 float startpos = elbow1.read();
marcbax 0:73e3587b65ec 382 int numsteps = (movetime * 50); //50 pulses/second, so each step is 1 servo pulse
marcbax 0:73e3587b65ec 383 for (int i=0; i<numsteps; i++) {
marcbax 0:73e3587b65ec 384 elbow1 = startpos + i * (endpos - startpos)/numsteps;
marcbax 0:73e3587b65ec 385 wait(movetime/numsteps);
marcbax 0:73e3587b65ec 386 }
marcbax 0:73e3587b65ec 387 elbow1 = endpos;
marcbax 0:73e3587b65ec 388 }
marcbax 0:73e3587b65ec 389
marcbax 0:73e3587b65ec 390 //moves elbow2 to a position in a specified time, allowing speed control
marcbax 0:73e3587b65ec 391 void elbow2move (float endpos, float movetime) {
marcbax 0:73e3587b65ec 392 float startpos = elbow2.read();
marcbax 0:73e3587b65ec 393 int numsteps = (movetime * 50); //50 pulses/second, so each step is 1 servo pulse
marcbax 0:73e3587b65ec 394 for (int i=0; i<numsteps; i++) {
marcbax 0:73e3587b65ec 395 elbow2 = startpos + i * (endpos - startpos)/numsteps;
marcbax 0:73e3587b65ec 396 wait(movetime/numsteps);
marcbax 0:73e3587b65ec 397 }
marcbax 0:73e3587b65ec 398 elbow2 = endpos;
marcbax 0:73e3587b65ec 399 }
marcbax 0:73e3587b65ec 400
marcbax 0:73e3587b65ec 401 //Performs a conditioning cycle. if tickle==0, no tickling takes place. Return==1 if a PER has been detected
marcbax 0:73e3587b65ec 402 int condcycle(int station, int tickle) {
marcbax 0:73e3587b65ec 403 int perseen;
marcbax 0:73e3587b65ec 404 perseen = 0;
marcbax 0:73e3587b65ec 405 //for station 1
marcbax 0:73e3587b65ec 406 if (station == 1) {
marcbax 0:73e3587b65ec 407 //dip brush
marcbax 0:73e3587b65ec 408 arm1move(arm1dippos, 0.5);
marcbax 0:73e3587b65ec 409 elbow1move(elbow1dippos, 0.3);
marcbax 0:73e3587b65ec 410 wait(diptime);
marcbax 0:73e3587b65ec 411 elbow1move(elbow1basepos, 0.3);
marcbax 0:73e3587b65ec 412 arm1move(arm1basepos, 0.5);
marcbax 0:73e3587b65ec 413 //switch air to supply trace vapour
marcbax 0:73e3587b65ec 414 airswitcher = 1; //air contains target vapour
marcbax 0:73e3587b65ec 415 display.printf("Vapour ON");
marcbax 0:73e3587b65ec 416 wait (0.5);
marcbax 0:73e3587b65ec 417 //tickle
marcbax 0:73e3587b65ec 418 if (tickle) { //if tickling, first tickle then wait for PER or timeout
marcbax 0:73e3587b65ec 419 elbow1move(elbow1ticklepos, 0.2);
marcbax 0:73e3587b65ec 420 arm1move(arm1ticklepos, 1.5); //slower move of arm towards bee
marcbax 0:73e3587b65ec 421 perseen = detectPER(1, tickletimeout); //tickle until timeout or PER detected
marcbax 0:73e3587b65ec 422 }
marcbax 0:73e3587b65ec 423 //or not tickle
marcbax 0:73e3587b65ec 424 else {
marcbax 0:73e3587b65ec 425 perseen = detectPER(1, tickletimeout); //if not tickling, wait for PER or timeout then move to pre-feeding position
marcbax 0:73e3587b65ec 426 arm1move(arm1ticklepos-0.05, 1); //move to position between LED and holder
marcbax 0:73e3587b65ec 427 elbow1move(elbow1ticklepos, 0.3);
marcbax 0:73e3587b65ec 428 }
marcbax 0:73e3587b65ec 429 //feeding only if you have tickled or a PER has been detected
marcbax 0:73e3587b65ec 430 if (tickle || perseen) { //only feed if a PER has been detector, or "tickle" is true
marcbax 0:73e3587b65ec 431 elbow1move(elbow1feedpos, 0.3);
marcbax 0:73e3587b65ec 432 arm1move(arm1feedpos, 0.3);
marcbax 0:73e3587b65ec 433 wait(feedtime);
marcbax 0:73e3587b65ec 434 arm1move(arm1ticklepos -0.05, 0.3);
marcbax 0:73e3587b65ec 435 elbow1move(elbow1ticklepos, 0.3);
marcbax 0:73e3587b65ec 436 }
marcbax 0:73e3587b65ec 437 //move back to base position
marcbax 0:73e3587b65ec 438 arm1 = arm1basepos; //use fast move here
marcbax 0:73e3587b65ec 439 elbow1 = elbow1basepos; //use fast move here
marcbax 0:73e3587b65ec 440 airswitcher = 0; //air valve to clean air
marcbax 0:73e3587b65ec 441 display.printf("\e[DFF\r"); //rewrite "ON" to "OFF" on display
marcbax 0:73e3587b65ec 442 }
marcbax 0:73e3587b65ec 443 //for station 2
marcbax 0:73e3587b65ec 444 if (station == 2) {
marcbax 0:73e3587b65ec 445 //dip brush
marcbax 0:73e3587b65ec 446 arm2move(arm2dippos, 0.5);
marcbax 0:73e3587b65ec 447 elbow2move(elbow2dippos, 0.3);
marcbax 0:73e3587b65ec 448 wait(diptime);
marcbax 0:73e3587b65ec 449 elbow2move(elbow2basepos, 0.3);
marcbax 0:73e3587b65ec 450 arm2move(arm2basepos, 0.5);
marcbax 0:73e3587b65ec 451 //switch air to supply trace vapour
marcbax 0:73e3587b65ec 452 //airswitcher = 1; //no air switching for station 2
marcbax 0:73e3587b65ec 453 wait (0.5);
marcbax 0:73e3587b65ec 454 //tickle
marcbax 0:73e3587b65ec 455 if (tickle) { //if tickling, first tickle then wait for PER or timeout
marcbax 0:73e3587b65ec 456 elbow2move(elbow2ticklepos, 0.2);
marcbax 0:73e3587b65ec 457 arm2move(arm2ticklepos, 1.5); //slower move of arm towards bee
marcbax 0:73e3587b65ec 458 perseen = detectPER(1, tickletimeout); //tickle until timeout or PER detected
marcbax 0:73e3587b65ec 459 }
marcbax 0:73e3587b65ec 460 //or not tickle
marcbax 0:73e3587b65ec 461 else {
marcbax 0:73e3587b65ec 462 perseen = detectPER(1, tickletimeout); //if not tickling, wait for PER or timeout then move to pre-feeding position
marcbax 0:73e3587b65ec 463 arm2move(arm2ticklepos-0.05, 1); //move to position between LED and holder
marcbax 0:73e3587b65ec 464 elbow2move(elbow2ticklepos, 0.3);
marcbax 0:73e3587b65ec 465 }
marcbax 0:73e3587b65ec 466 //feeding only if you have tickled or a PER has been detected
marcbax 0:73e3587b65ec 467 if (tickle || perseen) { //only feed if a PER has been detector, or "tickle" is true
marcbax 0:73e3587b65ec 468 elbow2move(elbow2feedpos, 0.3);
marcbax 0:73e3587b65ec 469 arm2move(arm2feedpos, 0.3);
marcbax 0:73e3587b65ec 470 wait(feedtime);
marcbax 0:73e3587b65ec 471 arm2move(arm2ticklepos -0.05, 0.3);
marcbax 0:73e3587b65ec 472 elbow2move(elbow2ticklepos, 0.3);
marcbax 0:73e3587b65ec 473 }
marcbax 0:73e3587b65ec 474 //move back to base position
marcbax 0:73e3587b65ec 475 arm2 = arm2basepos;
marcbax 0:73e3587b65ec 476 elbow2 = elbow2basepos;
marcbax 0:73e3587b65ec 477 }
marcbax 0:73e3587b65ec 478 return perseen;
marcbax 0:73e3587b65ec 479 }
marcbax 0:73e3587b65ec 480
marcbax 0:73e3587b65ec 481 //User to input choice between station 1 and 2 for this session
marcbax 0:73e3587b65ec 482 int stationchoice() {
marcbax 0:73e3587b65ec 483 int station;
marcbax 0:73e3587b65ec 484 station = 1;
marcbax 0:73e3587b65ec 485 cleardisplay(); //clear screen and home cursor
marcbax 0:73e3587b65ec 486 display.printf(" Station selection ");
marcbax 0:73e3587b65ec 487 display.printf("Left=1 2=Right");
marcbax 0:73e3587b65ec 488 while (lesw && risw) { //lesw and risw become false when pressed!
marcbax 0:73e3587b65ec 489 wait(0.02);
marcbax 0:73e3587b65ec 490 if (!lesw) station=1; //on LEFT select station 1
marcbax 0:73e3587b65ec 491 if (!risw) station=2; //on RIGHT select station 2
marcbax 0:73e3587b65ec 492 }
marcbax 0:73e3587b65ec 493 display.printf("\rStation %1u selected", station);
marcbax 0:73e3587b65ec 494 fprintf(logfile, "%3u, station selected\r", station);
marcbax 0:73e3587b65ec 495 return station;
marcbax 0:73e3587b65ec 496 }
marcbax 0:73e3587b65ec 497
marcbax 0:73e3587b65ec 498 //Registers and calibrates all beeholders used in this session
marcbax 0:73e3587b65ec 499 int registerbeeholders() {
marcbax 0:73e3587b65ec 500 int i;
marcbax 0:73e3587b65ec 501 bool done;
marcbax 0:73e3587b65ec 502 char buffert[30];
marcbax 0:73e3587b65ec 503 i = done = 0;
marcbax 0:73e3587b65ec 504 cleardisplay(); //clear screen and home cursor
marcbax 0:73e3587b65ec 505 fprintf(logfile, "calibration record:\r");
marcbax 0:73e3587b65ec 506 fprintf(logfile, "i, serialno, LED V, time\r");
marcbax 0:73e3587b65ec 507 while (i<30 && !done) { //register and calibrate a maximum of 30 beeholders
marcbax 0:73e3587b65ec 508 display.printf("calibrating %u\r",i+1);
marcbax 0:73e3587b65ec 509 sessionrecord[i].serialno = getserialno(station); //read serial number
marcbax 0:73e3587b65ec 510 if (sessionrecord[i].serialno != 0) { //check if serial number correctly read - if not it will be 0000
marcbax 0:73e3587b65ec 511 sessionrecord[i].calvalue = calibrate(station, 5); //5 calibration cycles
marcbax 0:73e3587b65ec 512 if ((sessionrecord[i].calvalue > 0.25) && (sessionrecord[i].calvalue < 0.97)) { //check that calvalue is in expected range
marcbax 0:73e3587b65ec 513 sessionrecord[i].tstamp = time(NULL); //create timestamp NOW
marcbax 0:73e3587b65ec 514 strftime(buffert, 20, "%X", localtime(&sessionrecord[i].tstamp)); //formats time part of timestamp
marcbax 0:73e3587b65ec 515 cleardisplay();
marcbax 0:73e3587b65ec 516 display.printf("SN %4u - cal %4.2fV\r", sessionrecord[i].serialno, sessionrecord[i].calvalue*3.3);
marcbax 0:73e3587b65ec 517 display.printf("OK for next\r");
marcbax 0:73e3587b65ec 518 display.printf("DOWN for training");
marcbax 0:73e3587b65ec 519 fprintf(logfile, "%4u,%6u,%6.2f, %s, calibrated\r", i, sessionrecord[i].serialno, sessionrecord[i].calvalue*3.3, buffert);
marcbax 0:73e3587b65ec 520 i++;
marcbax 0:73e3587b65ec 521 }
marcbax 0:73e3587b65ec 522 else {
marcbax 0:73e3587b65ec 523 cleardisplay();
marcbax 0:73e3587b65ec 524 display.printf("SN %4u - cal %4.2fV\r", sessionrecord[i].serialno, sessionrecord[i].calvalue*3.3);
marcbax 0:73e3587b65ec 525 display.printf("Cal out of range!\r");
marcbax 0:73e3587b65ec 526 multibeeps(2,0.5);
marcbax 0:73e3587b65ec 527 display.printf("OK to recalibrate\r");
marcbax 0:73e3587b65ec 528 fprintf(logfile, "%4u,%6u,%6.2f, %s, out of range\r", i, sessionrecord[i].serialno, sessionrecord[i].calvalue*3.3, buffert);
marcbax 0:73e3587b65ec 529 }
marcbax 0:73e3587b65ec 530 while (!done && oksw) { //loop until OK or DOWN are pressed
marcbax 0:73e3587b65ec 531 wait(0.02);
marcbax 0:73e3587b65ec 532 done = !dnsw; //DOWN exits registration cycle and moves to training
marcbax 0:73e3587b65ec 533 }
marcbax 0:73e3587b65ec 534 }
marcbax 0:73e3587b65ec 535 else { //retry when serialno can't be read (is 0000)
marcbax 0:73e3587b65ec 536 cleardisplay();
marcbax 0:73e3587b65ec 537 multibeeps(3,0.3); //beep-beep-beep when beeholder not correctly read
marcbax 0:73e3587b65ec 538 display.printf("invalid serial no\r");
marcbax 0:73e3587b65ec 539 display.printf("reseat beeholder\r");
marcbax 0:73e3587b65ec 540 display.printf("press OK");
marcbax 0:73e3587b65ec 541 while (oksw) wait(0.02); //loop until OK is pressed to start calibration loop again
marcbax 0:73e3587b65ec 542 }
marcbax 0:73e3587b65ec 543 cleardisplay();
marcbax 0:73e3587b65ec 544 }
marcbax 0:73e3587b65ec 545 return i; //upon done condition, i== number of beeholders calibrated
marcbax 0:73e3587b65ec 546 }
marcbax 0:73e3587b65ec 547
marcbax 0:73e3587b65ec 548 //gets holderrecord for the holder with a certain serial number
marcbax 0:73e3587b65ec 549 int getholderindex(int serialno) {
marcbax 0:73e3587b65ec 550 for (int i=0; i<numbeeholders; i++) { //reverse lookup of index for a certain serial number
marcbax 0:73e3587b65ec 551 if (sessionrecord[i].serialno == serialno) return i;
marcbax 0:73e3587b65ec 552 }
marcbax 0:73e3587b65ec 553 return 29; //if the record is not found, returns i==29
marcbax 0:73e3587b65ec 554 }
marcbax 0:73e3587b65ec 555
marcbax 0:73e3587b65ec 556 //all the elements making up a single training cycle with one beeholder
marcbax 0:73e3587b65ec 557 void trainingcycle() {
marcbax 0:73e3587b65ec 558 wait(0.2);
marcbax 0:73e3587b65ec 559 time_t tstamp = time(NULL); //create timestamp NOW
marcbax 0:73e3587b65ec 560 char buffert[30];
marcbax 0:73e3587b65ec 561 strftime(buffert, 20, "%X", localtime(&tstamp)); //format timestamp to time string
marcbax 0:73e3587b65ec 562 bool invalidserial;
marcbax 0:73e3587b65ec 563 invalidserial = 1;
marcbax 0:73e3587b65ec 564 int serialno;
marcbax 0:73e3587b65ec 565 serialno = 0;
marcbax 0:73e3587b65ec 566 while (invalidserial) { //loop until a serial number is read correctly
marcbax 0:73e3587b65ec 567 cleardisplay();
marcbax 0:73e3587b65ec 568 int serialno = getserialno(station); //read serial number
marcbax 0:73e3587b65ec 569 invalidserial = (serialno == 0); //if the serialno is 0, then it's invalid
marcbax 0:73e3587b65ec 570 if (invalidserial) {
marcbax 0:73e3587b65ec 571 display.printf("Invalid serialno\rReseat holder\rUP to retry");
marcbax 0:73e3587b65ec 572 while (upsw) wait(0.02); //loop until UP switch is pressed
marcbax 0:73e3587b65ec 573 }
marcbax 0:73e3587b65ec 574 }
marcbax 0:73e3587b65ec 575 int i = getholderindex(serialno); //get index i for serial number
marcbax 0:73e3587b65ec 576 IRledON(i); //switch IR LED on at correct brightness
marcbax 0:73e3587b65ec 577 sessionrecord[i].cycleno++; //increment cycle number for this beeholder
marcbax 0:73e3587b65ec 578 cleardisplay();
marcbax 0:73e3587b65ec 579 display.printf("SN: %4u, cycle %u\r", serialno, sessionrecord[i].cycleno);
marcbax 0:73e3587b65ec 580 sessionrecord[i].reslastcycle = condcycle(station, sessionrecord[i].ticklenextcycle); //do a conditioning cycle
marcbax 0:73e3587b65ec 581 fprintf(logfile, "%s,",buffert);
marcbax 0:73e3587b65ec 582 fprintf(logfile, " %4u,",serialno);
marcbax 0:73e3587b65ec 583 fprintf(logfile, " %2u,", sessionrecord[i].cycleno);
marcbax 0:73e3587b65ec 584 if (sessionrecord[i].reslastcycle) { //log PER or TimeOut
marcbax 0:73e3587b65ec 585 fprintf(logfile, " PER,");
marcbax 0:73e3587b65ec 586 }
marcbax 0:73e3587b65ec 587 else {
marcbax 0:73e3587b65ec 588 fprintf(logfile, " TO,");
marcbax 0:73e3587b65ec 589 }
marcbax 0:73e3587b65ec 590 fprintf(logfile, " training\r");
marcbax 0:73e3587b65ec 591 if (sessionrecord[i].reslastcycle) {
marcbax 0:73e3587b65ec 592 display.printf("PER detected\r");
marcbax 0:73e3587b65ec 593 }
marcbax 0:73e3587b65ec 594 else {
marcbax 0:73e3587b65ec 595 display.printf("PER time-out\r");
marcbax 0:73e3587b65ec 596 }
marcbax 0:73e3587b65ec 597 display.printf("mount holder + OK\r");
marcbax 0:73e3587b65ec 598 display.printf("DOWN to finish");
marcbax 0:73e3587b65ec 599 }
marcbax 0:73e3587b65ec 600
marcbax 0:73e3587b65ec 601 //main program
marcbax 0:73e3587b65ec 602 int main() {
marcbax 0:73e3587b65ec 603 initialise(); //initialise a new session
marcbax 0:73e3587b65ec 604
marcbax 0:73e3587b65ec 605 //Choose which station this session will use
marcbax 0:73e3587b65ec 606 station = stationchoice (); //menu to let user select station 1 or 2
marcbax 0:73e3587b65ec 607 cleardisplay();
marcbax 0:73e3587b65ec 608
marcbax 0:73e3587b65ec 609 //Choose substance string
marcbax 0:73e3587b65ec 610 substanceindex = subchoice(submenu); //menu to let use chose substance
marcbax 0:73e3587b65ec 611 fprintf(logfile, "%s\r", submenu[substanceindex].logstring); //prints the substance log string to the logfile
marcbax 0:73e3587b65ec 612
marcbax 0:73e3587b65ec 613 //Register and calibrate beeholders used in this session
marcbax 0:73e3587b65ec 614 display.printf("Now register holders\r");
marcbax 0:73e3587b65ec 615 display.printf("seat first holder\rpress OK\r");
marcbax 0:73e3587b65ec 616 while (oksw) wait(0.02); //loop so first beeholder can be mounted, then OK pressed
marcbax 0:73e3587b65ec 617 numbeeholders = registerbeeholders();
marcbax 0:73e3587b65ec 618 display.printf("%2u holders entered\r", numbeeholders);
marcbax 0:73e3587b65ec 619 wait(3);
marcbax 0:73e3587b65ec 620 cleardisplay();
marcbax 0:73e3587b65ec 621
marcbax 0:73e3587b65ec 622 //Conduct training
marcbax 0:73e3587b65ec 623 display.printf("Start training cycle\r");
marcbax 0:73e3587b65ec 624 display.printf("mount holder + OK\r");
marcbax 0:73e3587b65ec 625 display.printf("DOWN to finish");
marcbax 0:73e3587b65ec 626 fprintf(logfile, "Training started\r");
marcbax 0:73e3587b65ec 627 fprintf(logfile, "time, serial, cycleno, result\r");
marcbax 0:73e3587b65ec 628 wait(1);
marcbax 0:73e3587b65ec 629 InterruptIn oksw(p17); //redefine OK and footswitch as interrupts
marcbax 0:73e3587b65ec 630 oksw.mode(PullUp);
marcbax 0:73e3587b65ec 631 bool finishsession;
marcbax 0:73e3587b65ec 632 finishsession = 0;
marcbax 0:73e3587b65ec 633 oksw.fall(&trainingcycle); //call subroutine "trainingcycle" on OK/footswitch interrupt
marcbax 0:73e3587b65ec 634 while (!finishsession) { //loop while servicing interrupts
marcbax 0:73e3587b65ec 635 wait(0.02);
marcbax 0:73e3587b65ec 636 finishsession = !dnsw; //until DOWN button is pressed, which exits to program close
marcbax 0:73e3587b65ec 637 }
marcbax 0:73e3587b65ec 638
marcbax 0:73e3587b65ec 639 //Close logfile
marcbax 0:73e3587b65ec 640 fprintf(logfile, "session closed");
marcbax 0:73e3587b65ec 641 fclose(logfile); //close logfile for reading
marcbax 0:73e3587b65ec 642 cleardisplay();
marcbax 0:73e3587b65ec 643 display.printf("Session finished\r\rdownload etonlog.csvand rename");
marcbax 0:73e3587b65ec 644 }