Freeman Oldman / NUCLEO_STM32F401RE_CC3000_ILI9341
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 #include "mbed.h"
00002 #include "cmsis_os.h"
00003 #include "DHT.h"
00004 #include "SDFileSystem.h"
00005 #include "cc3000.h"
00006 #include "SPI_TFT_ILI9341.h"
00007 #include "Arial12x12.h"
00008 #include "Arial24x23.h"
00009 #include "Arial28x28.h"
00010 //#include "Arial34x40.h"
00011 //#include "Arial48x51.h"
00012 //#include "Arial35x38.h"
00013 #include "font_big.h"
00014 #include "Shell.h"
00015 #include "ini.h"
00016 #include "Utility.h"
00017 #include "HttpClient.h"
00018 #include "JsonParser.h"
00019 
00020 
00021 #include <vector>
00022 #include <string>
00023 #include <cstring>
00024 
00025 #include "TCPSocketConnection.h"
00026 #include "TCPSocketServer.h"
00027 
00028 using namespace mbed_cc3000;
00029 
00030 typedef struct
00031 {
00032         char startupimage[30];
00033     char webaddress[256];
00034     float imagedelay;
00035 } configuration;
00036 
00037 typedef struct
00038 {
00039     // Values read from DHT11
00040     double current_temperature;
00041     double current_humidity;
00042     double current_dewpoint;
00043     // Values read from openweathermap.com
00044     int weatherid;
00045     int sunrise;
00046     int sunset;
00047     double temperature;
00048     double humidity;
00049     double pressure;
00050     double windspeed;
00051     double clouds;
00052     std::string icon;
00053     std::string location;
00054     std::string description;
00055     
00056     void debug(Stream & strm)
00057     {
00058         strm.printf("Weather id : [%d]\r\n", weatherid);
00059         strm.printf("Current temperature: [%0.2f C]\r\n", current_temperature);
00060         strm.printf("Current humidity: [%0.2f%%]\r\n", current_humidity);
00061         strm.printf("Dew Point  : [%0.2f C]\r\n", current_dewpoint);
00062         strm.printf("Temperature: [%0.2f C]\r\n", temperature);
00063         strm.printf("Humidity   : [%0.2f%%]\r\n", humidity);
00064         strm.printf("Pressure   : [%0.2fhpa]\r\n", pressure);
00065         strm.printf("Wind Speed : [%%0.2f]\r\n", windspeed);
00066         strm.printf("Cloud Coverage: [%0.2f]\r\n", clouds);
00067         strm.printf("Location   : [%s]\r\n", location.c_str());
00068         strm.printf("Description: [%s]\r\n", description.c_str());
00069         strm.printf("Icon id    : [%s]\r\n", icon.c_str());
00070     }
00071 } weather_info;
00072 
00073 /* Define ALL Hardware used here and their pin configuration */
00074 Serial pc(USBTX, USBRX); // tx, rx
00075 DHT dht(D9, DHT11);
00076 //DigitalOut conLed(D6);        // PB_10
00077 DigitalIn shellSwitch(D6); // PB_0 (normally pulled high)
00078 I2C i2c(I2C_SDA, I2C_SCL); // SDA, SCL
00079 SDFileSystem sdcard(PB_15, PB_14, PB_13, PB_1, "sd"); // mosi, miso, sclk, cs, name
00080 // the TFT is connected to SPI pin 5-7
00081 SPI_TFT_ILI9341 TFT(PC_12, PC_11, PC_10, PC_0, PC_2, PC_3,"TFT");   // mosi, miso, sclk, cs, reset, dc
00082 DigitalOut lcdOn(PC_1);
00083 cc3000 wifi(PA_10, PA_8, PB_6, SPI(PA_7, PA_6, PA_5), "dlink-B15C", "fricu35860", WPA, false); //irq, en, cs, spi, irq-port
00084 
00085 
00086 /** Globals **/
00087 std::vector<std::string> images;
00088 char webdata[1024];
00089 configuration cfg;
00090 weather_info winfo;
00091 HeaderInfo info;
00092 
00093 
00094 static int confighandler(void* user, const char* section, const char* name,
00095                    const char* value)
00096 {
00097     configuration* pconfig = (configuration*)user;
00098 
00099     #define MATCH(s, n) strcmp(section, s) == 0 && strcmp(name, n) == 0
00100     if (MATCH("rotator", "imagedelay")) {
00101         pconfig->imagedelay = atof(value);
00102     } else if (MATCH("weather", "webaddress")) {
00103                 strncpy(pconfig->webaddress, value, sizeof(pconfig->webaddress));
00104         } else if (MATCH("boot", "startupimage")) {
00105               strncpy(pconfig->startupimage, value, sizeof(pconfig->startupimage));
00106     } else {
00107         return 0;  /* unknown section/name, error */
00108     }
00109     return 1;
00110 }
00111 
00112 /**
00113  *  \brief Setup interrupt priorities for Nucleo board
00114  *  \param none
00115  *  \return none
00116  */
00117 void init() 
00118 {
00119     // First and last IRQ defined in stm32f401xe.h
00120   int irqnum;
00121   for(irqnum = SysTick_IRQn ; irqnum < SPI4_IRQn + 1 ; irqnum++)
00122       NVIC_SetPriority((IRQn_Type)irqnum, 0x04);
00123     
00124   NVIC_SetPriority(SPI1_IRQn, 0x0);
00125   NVIC_SetPriority(FPU_IRQn, 0x1);
00126     NVIC_SetPriority(SPI2_IRQn, 0x2);
00127     NVIC_SetPriority(SPI3_IRQn, 0x02);
00128   NVIC_SetPriority(SysTick_IRQn, 0x3);  
00129 }
00130 
00131 /**
00132  * \brief Initialize CC3000
00133  * \param none
00134  * \return void
00135  **/
00136 void init_cc3000()
00137 {
00138     printf("Loading wifi startup settings ...\r\n");
00139     
00140   printf("Initializing cc3000 wifi ...\r\n");
00141   wifi.init();
00142     printf("Connecting to AP ...\r\n");
00143   if (wifi.connect() == -1) {
00144      printf("Failed to connect. Please verify connection details and try again. \r\n");
00145   } else {
00146      printf("IP address: %s \r\n", wifi.getIPAddress());
00147          printf("Gateway address: %s \r\n", wifi.getGateway());
00148          set_ctrl_panel(1, 1);
00149   }
00150 }
00151 
00152 /**
00153  * \brief Initialize LCD
00154  * \param none
00155  * \return void
00156  **/
00157 void init_LCD()
00158 {
00159         printf("Initializing LCD Screen ...\r\n");
00160     
00161         lcdOn = 1;
00162     
00163         TFT.claim(stdout);  
00164     TFT.set_orientation(1);
00165     TFT.background(Black);    // set background to black
00166     TFT.foreground(White);    // set chars to white
00167     TFT.cls();                // clear the screen
00168  
00169 
00170     TFT.set_font((unsigned char*) Arial12x12);
00171     TFT.locate(0,0);
00172 
00173 }
00174 /**
00175  * \brief Initialize switch/led panel on I2C bus
00176  * \param none
00177  * \return void
00178  **/
00179 void init_i2cpanel()
00180 {
00181         char cmd[2];
00182         // Setup direction reg for panel address 1
00183       cmd[0] = 0x00; // Last bit is input
00184         cmd[1] = 0x00;
00185         // Write to the command register
00186         i2c.write(I2C_CTR_PANEL_ADDR, cmd, 2);
00187     
00188         // Setup direction reg for panel address 2
00189         cmd[0] = 0x01;
00190         cmd[1] = 0x00;
00191         
00192         i2c.write(I2C_CTR_PANEL_ADDR, cmd, 2);
00193 
00194 }
00195 
00196 /**
00197  * \brief Counter thread to test rtos
00198  * \param arg arguments to the thread
00199  * \return none
00200  **/
00201 void counter_thread(void const *args) 
00202 {
00203         uint8_t count;
00204 
00205     while (true) 
00206         {
00207             set_ctrl_panel(0, count);
00208             
00209             count++;
00210         
00211       osDelay(1000);
00212     }
00213 }
00214 osThreadDef(counter_thread, osPriorityNormal, DEFAULT_STACK_SIZE);
00215 
00216 
00217 int find_images(const char * root, const char * ext)
00218 {
00219     DIR * dp;
00220     struct dirent * dirp;
00221     FILINFO fileInfo;
00222 
00223     dp = opendir(root);         
00224     while((dirp = readdir(dp)) != NULL)
00225     {
00226         if (sdcard.stat(dirp->d_name, &fileInfo) == 0)
00227         {
00228             if (!(fileInfo.fattrib & AM_DIR ))
00229             {
00230                 std::string filename = dirp->d_name;
00231                 std::size_t found = filename.find(ext);
00232                 if (found!=std::string::npos)
00233                 {
00234                     std::string fullpathname = root;
00235                     fullpathname += "/";
00236                     fullpathname += filename;
00237                     images.push_back(fullpathname);
00238                 }
00239             }
00240         }
00241     }
00242     closedir(dp);
00243     
00244     return images.size();
00245 }
00246 
00247 bool get_current_weather()
00248 {
00249       // First fetch current weather conditions from sensor
00250         pc.printf("Getting current conditions...\r\n");
00251       if(dht.readData() == ERROR_NONE)
00252         {
00253             float temperature = dht.ReadTemperature(CELCIUS);
00254             float humidity = dht.ReadHumidity();
00255             float dewpoint = dht.CalcdewPoint(temperature, humidity);
00256             
00257             winfo.current_temperature = temperature;
00258             winfo.current_humidity = humidity;
00259             winfo.current_dewpoint = dewpoint;
00260             
00261             pc.printf("Temperature : %.2f\r\n", temperature);
00262             pc.printf("Humidity : %.2f\r\n", humidity);
00263             pc.printf("Dew Point : %.2f\r\n", dewpoint);
00264             
00265             return true;
00266         }   else
00267             return false;
00268 }
00269 
00270 bool get_weather_info()
00271 {
00272         bool retval = false;
00273         HttpClient client("test.com");
00274             
00275         memset(webdata, 0, sizeof(webdata));
00276         
00277         // Fetch page from openweather
00278         pc.printf("\r\nTrying to fetch page [%s]... \r\n", cfg.webaddress);
00279         int ret = client.get(cfg.webaddress, webdata, sizeof(webdata), info);
00280         if (ret > 0)  
00281         {
00282             using namespace JSON;
00283             pc.printf("Page fetched successfully - read %d characters \r\n", strlen(webdata));
00284             pc.printf("Web Data [%s]\r\n", webdata);
00285             
00286             MVJSONReader reader(webdata);
00287             // pc.printf("Result: %s \r\n", webdata);
00288             if (reader.root->hasField("sys"))
00289             {
00290                     winfo.sunrise = reader.root->getField("sys")->getFieldInt("sunrise");
00291                     winfo.sunset = reader.root->getField("sys")->getFieldInt("sunset");
00292           winfo.location = reader.root->getFieldString("name");
00293                     winfo.temperature = reader.root->getField("main")->getFieldDouble("temp") - 273.15;
00294                     winfo.pressure = reader.root->getField("main")->getFieldDouble("pressure");
00295                     winfo.humidity = reader.root->getField("main")->getFieldDouble("humidity");
00296                     winfo.windspeed = reader.root->getField("wind")->getFieldDouble("speed");
00297                     winfo.clouds = reader.root->getField("clouds")->getFieldDouble("all");
00298                     if (reader.root->getField("weather") != NULL)
00299             if (reader.root->getField("weather")->size() > 0)
00300             {
00301                 // we take only first element from list
00302                 winfo.weatherid = reader.root->getField("weather")->at(0)->getFieldInt("id");
00303                 winfo.icon = reader.root->getField("weather")->at(0)->getFieldString("icon");
00304                 winfo.description = reader.root->getField("weather")->at(0)->getFieldString("description");
00305             }
00306                     retval = true;
00307             }   
00308         }else
00309             retval = false;
00310         
00311         return retval;
00312 }
00313 
00314 // Update LCD display based on weather info     
00315 void update_lcd(bool update_locale)
00316 {
00317     
00318         // TFT.cls();
00319         if (get_current_weather())
00320         {
00321             // Use large fonts to display temperature
00322             TFT.background(Black);
00323             TFT.foreground(White);
00324             TFT.locate(170, 120);
00325             TFT.set_font((unsigned char *) Neu42x35);
00326             TFT.printf("%.0f C",winfo.temperature);
00327 
00328             // At the bottom
00329             TFT.fillrect(0,185,320,216,Blue);
00330             TFT.background(Blue);
00331             TFT.foreground(White);
00332             TFT.set_font((unsigned char*) Arial28x28);
00333             TFT.locate(0,187);
00334             TFT.printf("%.0f%% Humidity", 
00335                 winfo.current_humidity);
00336             
00337             TFT.locate(0, 218);
00338             TFT.set_font((unsigned char *) Arial12x12);
00339             TFT.background(Black);
00340             TFT.foreground(White);
00341             TFT.printf("Dew Point : %0.2fC", winfo.current_dewpoint);
00342         }
00343         
00344         if (update_locale)
00345         {
00346             // Fill banner with white
00347             TFT.background(White);
00348             TFT.foreground(Black);
00349             TFT.fillrect(0,0,320,100, White);
00350             
00351             // Load the graphic icon 
00352             std::string filename = "/sd/icons/" + winfo.icon + ".bmp";
00353             TFT.BMP_16(0,10, filename.c_str());
00354             
00355             // Fill the header - top most of LCD with info
00356             TFT.locate(100,20);
00357             TFT.set_font((unsigned char *) Arial28x28);
00358             TFT.background(White);    // set background to black
00359             TFT.foreground(Black);    // set chars to white         
00360 
00361             TFT.printf("%s", winfo.location.c_str());
00362             TFT.locate(100,60);
00363             TFT.set_font((unsigned char *) Arial12x12);
00364             capitalize_word_start(winfo.description);
00365             TFT.printf("%s", winfo.description.c_str());
00366         }
00367             
00368     
00369 }
00370 
00371 static const ShellCommand cmds[] = {
00372     {"ls", cmd_ls},
00373     {"load", cmd_load},
00374     {"sensor", cmd_sensor},
00375     {"roll", cmd_rollimages},
00376     {NULL, NULL}
00377 };
00378 
00379 static const ShellConfig shell_cfg1 = {
00380   (Serial *) &pc,
00381   (ShellCommand *) cmds
00382 };
00383 
00384 int main() 
00385 {
00386    
00387     // Set NVIC interrupt priorities
00388     init();
00389     pc.baud(115200);
00390     i2c.frequency(100000);
00391     init_i2cpanel();
00392     
00393     bool startShell = (shellSwitch.read() == 0);
00394     pc.printf("Starting shell: [%s]\r\n", startShell ? "Yes":"No");
00395 
00396     int numbmps = find_images("/sd", ".bmp");
00397     pc.printf("Found %d bmps in directory /sd\r\n", numbmps);
00398     // Read the configuration file
00399     pc.printf("Reading /sd/config.ini ...\r\n");
00400   if (ini_parse("/sd/config.ini", confighandler, &cfg) < 0) {
00401         // Initialize the cfg 
00402         strcpy(cfg.webaddress, "http://192.168.1.75/hmap/booksearch.html");
00403         strcpy(cfg.startupimage, "boot.bmp");
00404         cfg.imagedelay = 1000;
00405   }
00406     
00407     pc.printf("Initializing hardware ...\r\n");
00408     init_cc3000();
00409     
00410     pc.printf("Starting counter leds ....\r\n");
00411     osThreadCreate(osThread(counter_thread), NULL);
00412     
00413     init_LCD(); 
00414 
00415     
00416     if (startShell)
00417     {
00418         pc.printf("Starting debug shell ...\r\n");
00419         shellStart(&shell_cfg1);
00420     }
00421     else
00422     {
00423 //      pc.printf("Starting image rotator ...\r\n");
00424       unsigned int count = 0;
00425         bool update_weather = true;
00426         while(true)
00427         {
00428                 // If we have an RTC, we can detect new day
00429                 if (update_weather && get_weather_info())
00430                 { 
00431                     winfo.debug(pc);
00432                     update_lcd(true);
00433         }
00434                 else
00435                     update_lcd(false);
00436     
00437         wait(5.0);
00438                 count++;
00439                 if ((count % 10) == 0)
00440                     update_weather = true;
00441                 else
00442                     update_weather = false;
00443                 
00444         
00445               //heapinfo(&pc);
00446 /*      
00447             for(std::vector<std::string>::iterator i = images.begin();
00448                 i != images.end(); i++)
00449             {
00450                 pc.printf("Loading image %s...\r\n", (*i).c_str());
00451                 TFT.cls();
00452                 int err = TFT.BMP_16(0,0, (*i).c_str());
00453                 if (err != 1) TFT.printf(" - Err: %d", err);
00454             
00455                 wait(1.0);
00456                 heapinfo(&pc);
00457             }
00458 */                      
00459         }
00460     }
00461 }
00462