The MBED firmware used on the Chipin sorter, developed over 12 weeks for a 3rd year university systems project. Chipin is a token sorter, it sorts tokens by colours and dispenses them to order through an online booking system and card reader. This program interfaces with an FPGA, PC and LCD screen to control the sorter. The sorter has an operation mode where it can process orders when a card is entered into the machine. There is also a maintenance mode where the device responds to maintenance instructions such as 'dispense all'. More information at http://www.ionsystems.uk/

Dependencies:   MCP23017 TCS3472_I2C WattBob_TextLCD mbed-rtos mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 bool operationMode      = true; //the MBED starts in operation mode.
00002 
00003 #include "mbed.h"
00004 Serial pc(USBTX, USBRX);
00005 Serial glcd(p13, p14);
00006 #include "rtos.h"
00007 #include "Language.h"
00008 DigitalIn languageButton(p30);
00009 Language currentLanguage = ENGLISH;
00010 #include <sstream>
00011 #include <string>
00012 #include "mbedStorage.h"
00013 #include "mbedLCD.h"
00014 #include "stateMachine.h"
00015 #include "FPGAcomms.h"
00016 #ifndef serialComm
00017 #define serialComm
00018 #include "serialCommunication.h"
00019 #endif
00020 
00021 
00022 DigitalOut led1(LED1);
00023 DigitalOut led2(LED2);
00024 DigitalOut led3(LED3);
00025 DigitalOut led4(LED4);
00026 
00027 StateMachine stateMachine;
00028 
00029 //Boolean values to easily enable and disable certain features for individual testing
00030 bool colourSensor   =   true;
00031 bool cardReader     =   true;
00032 bool sorter         =   true;
00033 bool dispensor      =   true;
00034 bool testFunctions  =   true;
00035 bool serialComms    =   true;
00036 
00037 int mode = 0;   //mode select
00038 int maintenanceModeSelect = 0;
00039 
00040 //Call to check if an MBED button is pressed
00041 bool buttonPressed(int buttonNumber)
00042 {
00043     if(buttonNumber > -1 && buttonNumber < 4) {
00044         return par_port->read_bit(buttonNumber + 8);
00045     }
00046     return false;
00047 }
00048 //Run a mode, defined by 'mode'.
00049 void checkSortDispenseButtons()
00050 {
00051 
00052     if(buttonPressed(3)) {
00053         mode = !mode;
00054     }
00055     /* NOTICE: Enable the modes below for more maintenace functions, good for debugging.
00056      */
00057 
00058 
00059     /*
00060         if(mode == 0) {                                    //Dispense Mode
00061             printLCD("Dispense Mode");
00062             operationMode=false;
00063             if(buttonPressed(0)) {
00064                 printLCD("Red Button pressed");
00065                 dispense(RED);
00066             } else if(buttonPressed(1)) {
00067                 printLCD("Green Button pressed");
00068                 dispense(GREEN);
00069             } else if(buttonPressed(2)) {
00070                 printLCD("Blue Button pressed");
00071                 dispense(BLUE);
00072             }
00073 
00074         } *//*else if(mode == 1) {                               //Sort Mode
00075 printLCD("Sort Mode");
00076 operationMode=false;
00077 if(buttonPressed(0)) {
00078 log("Red Button pressed");
00079 sort(RED);
00080 } else if(buttonPressed(1)) {
00081 log("Green Button pressed");
00082 sort(GREEN);
00083 } else if(buttonPressed(2)) {
00084 log("Blue Button pressed");
00085 sort(BLUE);
00086 }
00087 
00088 }*//* else if(mode == 2) {                               //Bin/Recycle Mode
00089 printLCD("Bin/Recycle Mode");
00090 operationMode=false;
00091 if(buttonPressed(0)) {
00092 log("Bin button pressed");
00093 sort(BIN);
00094 } else if(buttonPressed(1)) {
00095 log("Recycle Button");
00096 recycle();
00097 }
00098 } */
00099     /*else if(mode == 4) {                               //Card Reader Mode
00100         operationMode= true;
00101         if(cardReader && cardDetect) {
00102             cardAcquisition();
00103 
00104         }*/
00105     if(mode == 0) {                               //Storage Mode
00106         operationMode=true;
00107         stringstream ss;
00108         ss << "Operation:   " << "R:" << redAmount << "G:" << greenAmount << "B:" << blueAmount << "RE:" << recycleAmount;
00109         string tmp = ss.str();
00110         printLCD(tmp.c_str());
00111         wait(0.1);
00112         if(buttonPressed(0)) {
00113             //log("Dispense all button pressed");
00114             dispenseAll();
00115         } else if(buttonPressed(1)) {
00116             //log("Clear stored numbers button pressed");
00117             writeFile(0,0,0,recycleAmount);
00118             redAmount = 0;
00119             greenAmount = 0;
00120             blueAmount = 0;
00121             printLCD("Cleared values");
00122 
00123         } else if(buttonPressed(2)) {
00124             //log("Increment all stored values by 2.");
00125             redAmount += 2;
00126             greenAmount += 2;
00127             blueAmount += 2;
00128             writeFile(redAmount,greenAmount,blueAmount,recycleAmount);
00129 
00130             printLCD("set values to 2");
00131 
00132         }
00133     } else if(mode == 1) {
00134         operationMode = false;
00135         stringstream ss;
00136         ss << maintenanceModeSelect;
00137         string mainModeSelect = ss.str();
00138         printLCD("Maintenance: " + mainModeSelect);
00139         wait(0.1);                           //Maintenance Mode
00140        
00141         if(buttonPressed(0)) {                     //Next maintenance function
00142             maintenanceModeSelect++;
00143             if(maintenanceModeSelect > 13) maintenanceModeSelect = 0;
00144         } else if(buttonPressed(1)) {               //Previous maintenance function
00145             maintenanceModeSelect--;
00146             if(maintenanceModeSelect < 0) maintenanceModeSelect = 13;
00147         } else if(buttonPressed(2)) {              //Process Instruction
00148             switch(maintenanceModeSelect) {
00149                 case 0://RB_LEFT:
00150                     printLCD("Moving Red/Blue Slider left.");
00151                     maintain(RB_LEFT);
00152                     break;
00153 
00154                 case 1://RB_CENTRE:
00155                     printLCD("Centering Red/Blue Slider.");
00156                     maintain(RB_CENTRE);
00157                     break;
00158 
00159                 case 2://RB_RIGHT:
00160                     printLCD("Moving Red/Blue Slider right.");
00161                     maintain(RB_RIGHT);
00162                     break;
00163 
00164                 case 3://GO_UP:
00165                     printLCD("Moving Green Slider up.");
00166                     maintain(GO_UP);
00167                     break;
00168 
00169                 case 4://GO_CENTRE:
00170                     printLCD("Centering Green Slider.");
00171                     maintain(GO_CENTRE);
00172                     break;
00173 
00174                 case 5://GO_DOWN:
00175                     printLCD("Moving Green Slider down.");
00176                     maintain(GO_DOWN);
00177                     break;
00178 
00179                 case 6://BR_LEFT:
00180                     printLCD("Moving Bin Slider left.");
00181                     maintain(BR_LEFT);
00182                     break;
00183 
00184                 case 7://BR_RIGHT:
00185                     printLCD("Moving Bin Slider right.");
00186                     maintain(BR_RIGHT);
00187                     break;
00188 
00189                 case 8://R_PUSH:
00190                     printLCD("Pushing red dispensor");
00191                     maintain(R_PUSH);
00192                     break;
00193 
00194                 case 9://R_HOME:
00195                     printLCD("Homing red dispensor");
00196                     maintain(R_HOME);
00197                     break;
00198 
00199                 case 10://GB_LEFT:
00200                     printLCD("Pushing green dispensor");
00201                     maintain(GB_LEFT);
00202                     break;
00203 
00204                 case 11://GB_CENTRE:
00205                     printLCD("Centre green/blue dispensor");
00206                     maintain(GB_CENTRE);
00207                     break;
00208 
00209                 case 12://GB_RIGHT:
00210                     printLCD("Pushing blue dispensor");
00211                     maintain(GB_RIGHT );
00212                     break;
00213 
00214                 case 13: //MaintenanceEND
00215                     printLCD("Ending Maintenance Mode");
00216                     maintain(maintenanceEND);
00217                     break;
00218             }
00219             printLCD("Ready for next command");
00220             wait(1);
00221         }
00222     }
00223 }
00224 //Coordinate changing language on PC and Arduino.
00225 void changeLanguage()
00226 {
00227     currentLanguage = nextLanguage(currentLanguage);        //Change the language on teh MBED.
00228     sendLanguageCharacter();                                //Tell PC & Arduino to change language.
00229     wait(1);
00230 }
00231 
00232 /* void sortFunction()
00233  *  Read sensor and sort according to the colour.
00234  */
00235 void sortFunction()
00236 {
00237     //Read the colour twice and make sure both are the same. If not then return and try again.
00238     Thread::wait(100);
00239     Colour colour = readColourSensor();
00240     Thread::wait(100);
00241     Colour colour2 = readColourSensor();
00242     if(colour != colour2) {
00243         return;
00244     }
00245     //Ensure a bin read is valid by ensuring it is the same as earlier. Prevents a bin read being valid if the chip is out of place on the sensor.
00246     if(colour == BIN) {
00247         Thread::wait(100);
00248         Colour binCheck = readColourSensor();
00249         if(binCheck != colour) {
00250             return;
00251         }
00252     }
00253 
00254     //log("Sorting colour");
00255     sort(colour);
00256 }
00257 
00258 //Run sortFunction with a small delay between iterations, pulses LED.
00259 void sortMode(void const* args)
00260 {
00261     while(colourSensor && sorter) {
00262         if(operationMode) {
00263             led2 = 1;
00264             sortFunction();
00265             led2 = 0;
00266             Thread::wait(50);
00267         }
00268     }
00269 }
00270 
00271 bool pcReady = false;   //Defines  whether the PC is ready to accept characters on the COM port.
00272 //handles dispensing from a card, changing language
00273 void dispenseFunction()
00274 {
00275     if(!pcReady) {
00276         if(pc.getc() == '*') {
00277             pcReady = true;
00278         }
00279     } else {
00280         //Check language button
00281         if(languageButton) {
00282             changeLanguage();
00283         }
00284         if(cardReader && cardDetect) {
00285             //Read card
00286             int cardNumber = cardAcquisition();
00287 
00288             //Send message to pc
00289             pc.putc('*');
00290             wait(0.5);
00291 
00292             //Send card number to pc
00293             pc.printf("%i\n",cardNumber);
00294 
00295             int red = 0;
00296             int green = 0;
00297             int blue = 0;
00298 
00299             //Get order from pc, convert characters to integers.
00300             red = (int) pc.getc() - '0';
00301             green = (int) pc.getc() - '0';
00302             blue = (int) pc.getc() - '0';
00303 
00304             //Check if there are enough chips to dispense order
00305             Thread::wait(100);
00306             if(red > redAmount || green > greenAmount || blue > blueAmount) {
00307                 //If not then do not dispense
00308                 pc.putc('<');
00309                 pcReady = false;
00310             } else if(red ==0 && green == 0 && blue ==0) {
00311                 pc.putc('@');
00312                 pcReady = false;
00313             } else {
00314                 //Otherwise there are enough tokens so dispense the order
00315                 pc.putc('>');
00316 
00317                 //Display order on LCD
00318                 glcd.putc(27);
00319                 glcd.putc(18);
00320                 glcd.putc(red + '0'); //Convert int to char
00321                 glcd.putc(green + '0');//Convert int to char
00322                 glcd.putc(blue + '0');//Convert int to char
00323                 glcd.putc(255);
00324 
00325                 //Dispense Order
00326                 dispenseOrder(red,green,blue);
00327 
00328                 //Display finished dispensing on lcd
00329                 glcd.putc(27);
00330                 glcd.putc(19);
00331                 glcd.putc(255);
00332 
00333                 //Reset pc ready
00334                 pcReady = false;
00335                 wait(1);
00336                 pc.putc('(');
00337             }
00338 
00339         }
00340     }
00341 }
00342 //Runs dispenseFunction with a small delay between iterations, pulses LED.
00343 void dispenseMode(void const* args)
00344 {
00345 
00346     while(true) {
00347         if(operationMode) {
00348             led3 = 1;
00349             dispenseFunction();
00350             led3 =0;
00351             Thread::wait(50);
00352         }
00353 
00354     }
00355 }
00356 
00357 
00358 int main()
00359 {
00360     led1 = 0;
00361     setupLCD();
00362     printLCD("Welcome to the  Chipin Sorter");
00363     Thread::wait(1000);
00364     readChipNumbers();
00365     printStoredChipValues();
00366     printLCD("Resetting all sliders");
00367     maintain(maintenanceEND);   //reset sliders on FPGA
00368     printLCD("");
00369     Thread::wait(1000);
00370     sendLanguageCharacter();    //Synchronise language on PC and arduino
00371 
00372     Thread sortThread(sortMode);    //Start the sorting thread.
00373     if(!languageButton) {   //Decide whether to start in operation mode or maintenance mode.
00374         operationMode = true;
00375         mode = 0;
00376 
00377     } else {
00378         operationMode = false;
00379         mode = 1;
00380     }
00381     Thread dispenseThread(dispenseMode);    //Start the dispensing thread.
00382     while(true) {
00383         led1 = 1;   //pulse led1
00384         led4 = cardDetect;
00385 
00386         if(!operationMode) {    //Check for maintenance commands if in maintenance mode.
00387             checkSerial();
00388         }
00389         if(testFunctions) checkSortDispenseButtons();   //Run the MBED modes if enabled.
00390         Thread::wait(100);
00391         led1=0;
00392         Thread::wait(100);
00393     }
00394 }