Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
main.cpp
00001 // Display Test 00002 #include "KS0108.h" 00003 #include "calsolimage.h" 00004 #include "MyPhone_20.h" 00005 #include "MyPhone_40.h" 00006 #include "rtos.h" 00007 00008 // Declare each of the things you're going to use 00009 00010 // The display 00011 KS0108 display(p23,p21,p22,p20,p24,p25,p17,p18,p19,p30,p29,p28,p27,p26); 00012 // The button on the breadboard 00013 DigitalIn topButton(p13); 00014 // For printing things to the computer 00015 Serial pc(USBTX,USBRX); 00016 00017 // Timers 00018 Timer timer; 00019 Timer testTimer; 00020 00021 //Methods 00022 void readFromCAN(); 00023 void setupScreen(); 00024 void updateBattery(int newVoltage); 00025 void updateBatteryGraphic(int newPercentage, int percentage); 00026 void printCenteredInt(int newInt, int oldInt, int startX, int startY, int charWidth, int charHeight, int charSpacing, int maxDigits); 00027 void printCenteredInt(int newInt, int oldInt, int leftLimit, int rightLimit, int startY, int charWidth, int charHeight, int charSpacing, int maxDigits); 00028 void printRightJustifiedInt(int newInt, int oldInt, int startX, int startY, int charWidth, int charHeight, int charSpacing, int maxDigits); 00029 00030 // Constants 00031 00032 //Maximum voltage for battery = 151.2 V (4.2V per cell, 36 cells total) 00033 const double MaxVoltage = 151.2; 00034 //Minimum voltage for battery = 108 V (3V per cell, 36 cells total) 00035 const double MinVoltage = 108; 00036 00037 // Mutex and screen state 00038 Mutex screen_mutex; 00039 CAN can(p9, p10); 00040 int demo = 0; 00041 00042 00043 //Speed: int from 0 to 999, in mph 00044 int speed = 0, newSpeed = 0; 00045 //Voltage: int from MinVoltage to MaxVoltage, in volts 00046 int voltage = MinVoltage, newVoltage = MinVoltage; 00047 //Current: int from 0 to 9999, in milliAmps 00048 int amperage = 0, newAmperage = 0; 00049 00050 00051 //Union type to make float to char conversion easier (used to read CAN messages) 00052 typedef union _data 00053 { 00054 float f[2]; 00055 char s[8]; 00056 } floatchar; 00057 00058 //Union type to make int to char conversion easier (used to read CAN messages) 00059 typedef union _data2 00060 { 00061 uint16_t i[4]; 00062 char s[8]; 00063 } intchar; 00064 00065 00066 /* Input thread - Modifies state variables based on input */ 00067 void input_runner(void const *argument) { 00068 while (true) { 00069 // If top button is pressed, don't accept other input 00070 if (!topButton) { 00071 // Debounce wait 00072 Thread::wait(100); 00073 if (!topButton) { 00074 screen_mutex.lock(); 00075 demo++; 00076 if (demo > 1) { 00077 demo = 0; 00078 } 00079 screen_mutex.unlock(); 00080 } 00081 // Don't accept other input while button is pressed 00082 while(!topButton) { 00083 Thread::wait(100); 00084 } 00085 } 00086 } 00087 } 00088 00089 00090 // This is where your programs starts running 00091 int main() 00092 { 00093 // Initialize variables** 00094 int current_demo = demo; 00095 topButton.mode(PullUp); 00096 // Display CalSol logo 00097 display.FullScreenBMP(pic); 00098 Thread::wait(200); 00099 00100 timer.start(); 00101 00102 // Start the button thread 00103 Thread button_thread(input_runner); 00104 00105 // Main thread 00106 while(1) { 00107 // First, check if the state has changed, if so, wipe the screen 00108 int changed = 0; 00109 screen_mutex.lock(); 00110 if (current_demo != demo) 00111 { 00112 changed = 1; 00113 } 00114 current_demo = demo; 00115 screen_mutex.unlock(); 00116 00117 // Wipe the screen 00118 if (changed) 00119 { 00120 display.ClearScreen(); 00121 changed = 0; 00122 } 00123 00124 // Now run the actual program 00125 switch(current_demo) 00126 { 00127 // Demo 0: Just display the CalSol logo 00128 case 0: 00129 if(timer.read_ms() > 500) 00130 { 00131 display.FullScreenBMP(pic); 00132 timer.reset(); 00133 } 00134 break; 00135 00136 // Demo 1: Display a mock speedometer, with battery level 00137 case 1: 00138 //Initialize variables 00139 speed = newSpeed = 60; 00140 amperage = newAmperage = 900; 00141 voltage = newVoltage = MaxVoltage; 00142 00143 setupScreen(); 00144 testTimer.start(); 00145 00146 //Display values as they are being changed 00147 while (true) 00148 { 00149 /* This part tests the printing 00150 00151 //Randomly selects values between appropriate ranges. 00152 speed = (int)(rand()%200); 00153 amperage = (int)(rand()%1000); 00154 voltage = (int)(rand()%100); 00155 00156 //Changes values from 1 to 3 or 4 digits to test proper spacing and erasing with changing num of digits 00157 if (testTimer.read_ms()%1000 == 0) 00158 { 00159 switch ((testTimer.read_ms()/1000)%4) 00160 { 00161 case 0: //1 digit 00162 newSpeed = (int)(rand()%9)+1; 00163 newAmperage = (int)(rand()%9)+1; 00164 break; 00165 case 3: //2 digits 00166 newSpeed = (int)(rand()%90)+10; 00167 newAmperage = (int)(rand()%90)+10; 00168 break; 00169 case 2: //3 digits 00170 newSpeed = (int)(rand()%900)+100; 00171 newAmperage = (int)(rand()%900)+100; 00172 break; 00173 case 1: //4 digits 00174 newSpeed = (int)(rand()%90)+100; 00175 newAmperage = (int)(rand()%900)+1000; 00176 break; 00177 default: break; 00178 } 00179 }*/ 00180 00181 //Keeps screen from updating too much 00182 if (testTimer.read_ms()%1000==0) 00183 { 00184 /* More printing testing 00185 00186 //Randomly increases or decreases values within a small range 00187 newSpeed += (int)((rand()%5)-2); 00188 newAmperage += (int)((rand()%21)-10); 00189 newVoltage += (int)((rand()%3)-1); 00190 00191 //Keeps voltage between allowed values 00192 if (newVoltage < MinVoltage || newVoltage > MaxVoltage) 00193 newVoltage = MaxVoltage; 00194 */ 00195 00196 readFromCAN(); 00197 00198 updateBattery(newVoltage); 00199 00200 //Updates speed 00201 display.SelectFont(MyPhone_40, BLACK, ReadData); 00202 printCenteredInt(newSpeed, speed, 12, 16, 15, 23, 1, 3); 00203 speed = newSpeed; 00204 00205 //Updates amperage 00206 display.SelectFont(MyPhone_20, BLACK, ReadData); 00207 printCenteredInt(newAmperage, amperage, 76, 40+8, 8, 11, 1, 4); 00208 amperage = newAmperage; 00209 } 00210 } 00211 break; 00212 default: break; 00213 } 00214 } 00215 } 00216 00217 void setupScreen() 00218 { 00219 //Draws grid lines to separate the screen. 00220 //Dimensions: (Speed) 70x64, (Battery) 57x42, (Amperage) 57x22 00221 display.HLineShort(71, 42, 57, BLACK); 00222 display.VLineShort(71, 0, 64, BLACK); 00223 00224 //This covers the stray black pixel... 00225 display.SetPixel(71-5, 42, WHITE); 00226 00227 //Draws the outline for battery graphic. Dimensions: 40x24, 4x8 00228 display.RoundRectangle(82, 4, 40, 24, 4, BLACK); 00229 display.EmptyRectangle(78, 12, 78+4, 12+8, BLACK); 00230 00231 //Prints MPH 00232 display.SelectFont(System5x7, BLACK, ReadData); 00233 display.GotoXY(26, 48); 00234 display.PrintString("MPH"); 00235 00236 //Print mAmp 00237 display.SelectFont(System5x7, BLACK, ReadData); 00238 display.GotoXY(114, 24+24); 00239 display.PrintString("mA"); 00240 00241 //Prints the percent sign 00242 display.GotoXY(108, 24+8); 00243 display.PrintString("%"); 00244 00245 //Draws initial shaded box for battery 00246 display.FullRectangle(86+(int)(((double)(100-((newVoltage - MinVoltage)/(MaxVoltage - MinVoltage)*100))/100.0)*32), 4+4, 86+32, 4+24-4, BLACK); 00247 } 00248 00249 //This exists to fix the problem with the percentage printing that was occuring for unknown reasons. 00250 //Writes an int to the screen right-justified over another int. 00251 void printRightJustifiedPercentage(int newInt, int oldInt, int startX, int startY, int charWidth, int charHeight, int charSpacing, int maxDigits) 00252 { 00253 for (int digits = maxDigits; digits > 0; digits--) 00254 { 00255 if (newInt >= (int)pow(10.0, digits-1)) 00256 { 00257 //Instead of checking if digits need to be erased, all digits will be erased 00258 //Erases digits that will not be covered by new text. 00259 display.FullRectangle(startX, startY, startX + (charWidth+charSpacing) * (maxDigits - digits), startY + charHeight, WHITE); 00260 display.GotoXY(startX + (charWidth+charSpacing) * (maxDigits - digits), startY); 00261 //Break out of loop. 00262 digits = -1; 00263 } 00264 } 00265 display.PrintNumber(newInt); 00266 } 00267 00268 //Writes an int to the screen center-justified over another int. 00269 void printCenteredInt(int newInt, int oldInt, int startX, int startY, int charWidth, int charHeight, int charSpacing, int maxDigits) 00270 { 00271 for (int digits = maxDigits; digits > 0; digits--) 00272 { 00273 //If current value has "digits" number of digits 00274 if (newInt >= (int)pow(10.0, digits-1)) 00275 { 00276 //If previous value had more digits than current value 00277 if (oldInt >= (int)pow(10.0, digits)) 00278 { 00279 //Erases all possible digits that could be on screen. 00280 //**First parameter should logically be startX, but it starts erasing 1 pixel too far to the right for some reason. ??? 00281 display.FullRectangle(startX-1, startY, startX + maxDigits*(charWidth+charSpacing), startY + charHeight, WHITE); 00282 } 00283 display.GotoXY(startX + 0.5*((maxDigits - digits)*charWidth + (maxDigits - digits - 1)*charSpacing), startY); 00284 //Break out of loop. 00285 digits = -1; 00286 } 00287 } 00288 display.PrintNumber(newInt); 00289 } 00290 00291 //Updates the battery graphic and prints corresponding percentage or voltage. 00292 void updateBattery(int newVoltage) 00293 { 00294 //These are needed for the battery graphic, even if the values won't be displayed. 00295 int percentage = (voltage - MinVoltage)/(MaxVoltage - MinVoltage)*100; 00296 int newPercentage = (newVoltage - MinVoltage)/(MaxVoltage - MinVoltage)*100; 00297 00298 //This line fixes the printing problem with the percentage that was caused by drawing shaded rectangle. Might have something to do with the method WriteInstruction(int, int) used by both methods. 00299 display.SetPixel(88, 32, WHITE); 00300 00301 // ** Problem: after a while of letting it run, sometimes a 0 will show up 1 pxl to the right of the hundreds place. But it gets erased when voltage drops enough 00302 //Prints percentage 00303 display.SelectFont(System5x7, BLACK, ReadData); 00304 printRightJustifiedPercentage(newPercentage, percentage, 88, 32, 5, 7, 1, 3); 00305 00306 //Prints voltage -- currently NOT IN USE 00307 /*display.SelectFont(System5x7, BLACK, ReadData); 00308 display.GotoXY(108, 24+8); 00309 display.PrintString("V"); 00310 display.SelectFont(System5x7, BLACK, ReadData); 00311 printRightJustifiedInt(newVoltage, voltage, 88, 32, 5, 7, 1, 3);*/ 00312 00313 updateBatteryGraphic(newPercentage, percentage); 00314 00315 percentage = newPercentage; 00316 voltage = newVoltage; 00317 } 00318 00319 //Changes shaded area of graphic to reflect current battery level. Dimensions 32x16 00320 void updateBatteryGraphic(int newPercentage, int percentage) 00321 { 00322 //Stores x-coordinates of shaded part of battery. 00323 int barX = 86+(int)(((double)(100-percentage)/100.0)*32); 00324 int newBarX = 86+(int)(((double)(100-newPercentage)/100.0)*32); 00325 00326 //Draws increase in percentage. 00327 if (newBarX < barX) 00328 { 00329 display.FullRectangle(newBarX, 4+4, barX, 4+24-4, BLACK); 00330 } 00331 //Draws decrease. 00332 else 00333 { 00334 display.FullRectangle(86, 4+4, newBarX, 4+24-4, WHITE); 00335 } 00336 } 00337 00338 //***This method has NOT BEEN TESTED. 00339 00340 //Gets information about speed, voltage, current, and battery life through CAN. 00341 void readFromCAN() 00342 { 00343 const int speedID = 0x403; 00344 const int voltageAmperageID = 0x523; 00345 00346 //Gets message from CAN. 00347 CANMessage msg; 00348 can.read(msg); 00349 int id = msg.id; 00350 00351 switch (id) 00352 { 00353 case voltageAmperageID: //contains four messages: voltage 1 and 2 in volts, current 1 and 2 in mA. each is an int (2 bytes) 00354 00355 //Read & store amperage value. 00356 intchar amp_data; 00357 for (int i = 0; i < 2; i++){ 00358 amp_data.s[i] = msg.data[i]; 00359 } 00360 amperage = amp_data.i[0]; //***is this correct? 00361 00362 //Read & store voltage/battery life value. 00363 floatchar volt_data; 00364 for (int i = 0; i < 2; i++){ 00365 volt_data.s[i] = msg.data[i+4]; 00366 } 00367 voltage = volt_data.f[0]; //***should this be reading voltage 1 or voltage 2? (volt1.f[0 or 1]) 00368 break; 00369 00370 case speedID: 00371 //** This packet actually contains motor velocity in rpm as well as vehicle velociy in m/s. How do I get only the second part? 00372 floatchar speed_data; 00373 for (int i = 0; i < 4; i++) { 00374 speed_data.s[i] = msg.data[i]; 00375 } 00376 //Conversion factor: 1 m/s = 2.23693629 mph 00377 speed = (speed_data.f[2])*2.23693629; //** should this be a combination of f[2] and f[3]? 00378 break; 00379 default: break; 00380 } 00381 }
Generated on Wed Jul 13 2022 22:03:27 by
1.7.2