|
|||
/* Programmname: e-Vertical Kraft Messung Version: 2.0 vom 02.05.2018 Beschreibung: Es wird zunaecht eine Netzwerkverbindung aufgebaut. Anschließend werden die vom Sensor erfassten Daten zum Webbrowser übermittelt */ //Library fuer OLED Display #include <Wire.h> // I2C #include <Adafruit_GFX.h> // OLED #include <Adafruit_SSD1306.h> // Graphic #define OLED_RESET 4 Adafruit_SSD1306 display(OLED_RESET); //Library fuer Acces Point ESP32 #include <WiFi.h> #include <SD.h> #include "SDCard.h" #include "FS.h" #include "SD.h" #include "SPI.h" // SPI bus //Library fuer waegezellen #include "cWaage.h" //Library fuer bluetooth #include <BLEDevice.h> #include <BLEServer.h> #include <BLEUtils.h> #include <BLE2902.h> #define SERVICE_UUID "6E400001-B5A3-F393-E0A9-E50E24DCCA9E" // UART service UUID #define CHARACTERISTIC_UUID_RX "6E400002-B5A3-F393-E0A9-E50E24DCCA9E" #define CHARACTERISTIC_UUID_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E" //**************************************************************************************************************************** BLECharacteristic *pCharacteristic; bool deviceConnected = false; float txValue = 0; //std::string rxValue; // Could also make this a global var to access it in loop() typedef struct Timestempel { int millisec = 0; int seconds = 0; int minutes = 0; int hours = 0; int gesamt = 0; } Timestempel; typedef struct Waagedata { Timestempel Time; float kraft1 = 0; float kraft2 = 0; float kraft3 = 0; float kraft4 = 0; } Waagedata; typedef struct charWaagedata { char hours[5]; char minutes[5]; char seconds[5]; char millisec[5]; char kraft1[10]; char kraft2[10]; char kraft3[10]; char kraft4[10]; } charWaagedata; cWaage Waage1, Waage2, Waage3, Waage4; Waagedata Daten; charWaagedata charDaten; class MyServerCallbacks: public BLEServerCallbacks { void onConnect(BLEServer* pServer) { deviceConnected = true; }; void onDisconnect(BLEServer* pServer) { deviceConnected = false; } }; class MyCallbacks: public BLECharacteristicCallbacks { void onWrite(BLECharacteristic *pCharacteristic) { std::string rxValue = pCharacteristic->getValue(); char *token; char input[20]; if (rxValue.length() > 0) { Serial.println("*********"); Serial.print("Received Value: "); for (int i = 0; i < rxValue.length(); i++) { input[i]= rxValue[i]; Serial.print(input[i]); } Serial.println(); // Do stuff based on the command received from the app if (rxValue.find("a") != -1) { token = strtok(input,"a"); while (token != NULL) //Pharsing Process : Bluetooth Input extrahieren, Werte in Variabeln übergeben { // Serial.print(atoi(token)); Waage1.initialisierung(26, atoi(token)); token = strtok(NULL, "a"); } } else if (rxValue.find("b") != -1) { token = strtok(input,"b"); while (token != NULL) //Pharsing Process : Bluetooth Input extrahieren, Werte in Variabeln übergeben { // Serial.print(atoi(token)); Waage2.initialisierung(25, atoi(token)); token = strtok(NULL, "b"); } } else if (rxValue.find("c") != -1) { token = strtok(input,"c"); while (token != NULL) //Pharsing Process : Bluetooth Input extrahieren, Werte in Variabeln übergeben { // Serial.print(atoi(token)); Waage3.initialisierung(33, atoi(token)); token = strtok(NULL, "c"); } } else if (rxValue.find("d") != -1) { token = strtok(input,"d"); while (token != NULL) //Pharsing Process : Bluetooth Input extrahieren, Werte in Variabeln übergeben { // Serial.print(atoi(token)); Waage4.initialisierung(32, atoi(token)); token = strtok(NULL, "d"); } } else if (rxValue.find("m") != -1) { token = strtok(input,"m"); while (token != NULL) //Pharsing Process : Bluetooth Input extrahieren, Werte in Variabeln übergeben { Serial.print("weight: "); Serial.print(atoi(token)); token = strtok(NULL, "m"); } } else if (rxValue.find("e") != -1) { Waage1.kalibrieren(); Serial.print("waage1"); } else if (rxValue.find("f") != -1) { Waage2.kalibrieren(); Serial.print("waage2"); } else if (rxValue.find("g") != -1) { Waage3.kalibrieren(); Serial.print("waage3"); } else if (rxValue.find("h") != -1) { Waage4.kalibrieren(); Serial.print("waage4"); } Serial.println(); Serial.println("*********"); } } }; //**************************************************************************************************************************** const char* ssid = "ESP32eVert"; const char* password = "12345678"; IPAddress myIP; WiFiServer server(80); WiFiClient client; // size of buffer used to capture HTTP requests #define REQ_BUF_SZ 50 char HTTP_req[REQ_BUF_SZ] = {0}; // buffered HTTP request stored as null terminated string char req_index = 0; // index into HTTP_req buffer //**************************************************************************************************************************** const char* file = "/Data3/index.txt"; const char* savefile = "/Data3/save.txt"; #define LOGDATEI "/Log" const char* dateiName = LOGDATEI "00.csv"; // Z.B. DHT11.csv File webFile; // the web page file on the SD card File dataFile; //**************************************************************************************************************************** void printDeviceInformation() { Serial.println(); Serial.println("-------------------------------------------------------------------------------------------------" ); Serial.print("Chip ID: "); Serial.println(ESP.getChipRevision()); Serial.print("Free Heap Size: "); Serial.println(ESP.getFreeHeap()); Serial.print("Chip Size: "); Serial.println(ESP.getFlashChipSize()); Serial.print("Chip Speed: "); Serial.print((float)ESP.getFlashChipSpeed() / 1000000); Serial.println("Mhz"); Serial.print("Chip Mode: "); Serial.println(ESP.getFlashChipMode()); Serial.println("-------------------------------------------------------------------------------------------------" ); Serial.println(); } void I2CDisplayEinstellung() { display.begin(SSD1306_SWITCHCAPVCC, 0x3C);// mit I2C-Adresse 0x3c initialisieren display.display(); // Zeigt Adafruit Initialisation Symbol delay(2000); // 2000ms = 2s display.clearDisplay(); display.setTextSize(1); display.setTextColor(INVERSE); } void AccesPointEinstellung(const char* _ssid, const char* _password) { Serial.begin(115200); // Connect to WiFi network Serial.println(); Serial.print(F("Connecting to ")); Serial.println(ssid); WiFi.mode(WIFI_AP); WiFi.softAP(ssid, password); delay(1000); myIP = WiFi.softAPIP(); // Start the server server.begin(); Serial.println(F("Server started")); } void printWifiInfo() { byte mac[6]; Serial.println(); Serial.println("-------------------------------------------------------------------------------------------------" ); Serial.print("SSID: "); Serial.println(ssid); Serial.print("IP Address: "); Serial.println(myIP); WiFi.macAddress(mac); Serial.print("Device MAC Address: "); for (int i = 5; i >= 1; i--) { Serial.print(mac[i], HEX); Serial.print(":"); } Serial.println(mac[0]); Serial.print("Signal strength (RSSI): "); Serial.print(WiFi.RSSI()); Serial.println(" dBm"); Serial.println("-------------------------------------------------------------------------------------------------" ); Serial.println(); } void SDKarteEinstellung() { // SD Karte Adapter Einstellungen Serial.println("Initializing SD card..."); if (!SD.begin()) { Serial.println("ERROR - SD card initialization failed!"); return; } uint8_t cardType = SD.cardType(); if (cardType == CARD_NONE) { Serial.println("No SD card attached"); return; } Serial.print("SD Card Type: "); if (cardType == CARD_MMC) { Serial.println("MMC"); } else if (cardType == CARD_SD) { Serial.println("SDSC"); } else if (cardType == CARD_SDHC) { Serial.println("SDHC"); } else { Serial.println("UNKNOWN"); } uint64_t cardSize = SD.cardSize() / (1024 * 1024); Serial.printf("SD Card Size: %lluMB\n", cardSize); Serial.println("SUCCESS - SD card initialized."); Serial.println("-------------------------------------------------------------------------------------------------" ); Serial.println(); } void IndexFilefinden() { // check for index.htm file if (!SD.exists(file)) { Serial.println("ERROR - Can't find index.txt file!"); return; // can't find index file } Serial.println("SUCCESS - Found index.txt file."); const uint8_t NAMENSLAENGE = sizeof(LOGDATEI) - 1; /* while (SD.exists(dateiName)) { if (dateiName[NAMENSLAENGE + 1] != '9') { dateiName[NAMENSLAENGE + 1]++; } else if (dateiName[NAMENSLAENGE] != '9') { dateiName[NAMENSLAENGE + 1] = '0'; dateiName[NAMENSLAENGE]++; } else { Serial.println("Kann Datei nicht erzeugen"); } } */ //writeFile(SD, savefile, "Hello "); dataFile = SD.open(dateiName, FILE_WRITE); Serial.print("SUCCESS - create "); Serial.println(dateiName); } void HeaderErstellen() { File file = SD.open(dateiName, FILE_APPEND); if (!file) { Serial.println("Failed to open file for appending"); return; } else { file.println(F("Messungen von 1:4 Multikopter")); file.print(F("Zeit")); file.print(','); file.print(F("Kraft1")); file.print(','); file.print(F("Kraft2")); file.print(','); file.print(F("Kraft3")); file.print(','); file.print(F("Kraft4")); file.print(','); file.println(); Serial.println("Set-up header"); file.close(); } } void WaagezelleEinstellung() { //Waage_name.initialisierung(int DATA_PIN, float calibrierungsfaktor) Waage1.initialisierung(26, 51.04); Waage2.initialisierung(25, 51.04); Waage3.initialisierung(33, 51.04); Waage4.initialisierung(32, 51.04); } //void Waagekalibrrierungsfunktion() { // Waage1.kalibrieren(); // Waage2.kalibrieren(); // Waage3.kalibrieren(); // Waage4.kalibrieren(); //} void setup() { //rtc_clk_cpu_freq_set(RTC_CPU_FREQ_80M); printDeviceInformation(); AccesPointEinstellung(ssid, password); I2CDisplayEinstellung(); printWifiInfo(); SDKarteEinstellung(); IndexFilefinden(); WaagezelleEinstellung(); HeaderErstellen(); //Waagekalibrrierungsfunktion() // uncommentieren wenn kalibrieren wollen. // Create the BLE Device BLEDevice::init("E-Vertical"); // Give it a name // Create the BLE Server BLEServer *pServer = BLEDevice::createServer(); pServer->setCallbacks(new MyServerCallbacks()); // Create the BLE Service BLEService *pService = pServer->createService(SERVICE_UUID); // Create a BLE Characteristic pCharacteristic = pService->createCharacteristic( CHARACTERISTIC_UUID_TX, BLECharacteristic::PROPERTY_NOTIFY ); pCharacteristic->addDescriptor(new BLE2902()); BLECharacteristic *pCharacteristic = pService->createCharacteristic( CHARACTERISTIC_UUID_RX, BLECharacteristic::PROPERTY_WRITE ); pCharacteristic->setCallbacks(new MyCallbacks()); // Start the service pService->start(); // Start advertising pServer->getAdvertising()->start(); Serial.println("Waiting a client connection to notify..."); } void BLE_Kalibrierung(cWaage an, cWaage bn, cWaage cn, cWaage dn){ // new function while(deviceConnected) { float a,b,c,d; //Waagekalibrrierungsfunktion(); //send get.unit aktuell char txString[32]; // make sure this is big enuffz // dtostrf(txValue, 1, 2, txString); // float_val, min_width, digits_after_decimal, char_buffer a = an.getGewicht(); b = bn.getGewicht(); c = cn.getGewicht(); d = dn.getGewicht(); String str= String(a) + '?' + String(b) + '?' + String(c) + '?' + String(d); Serial.println(str); str.toCharArray(txString,16); pCharacteristic->setValue(txString); pCharacteristic->notify(); // Send the value to the app! Serial.print("*** Sent Value: "); Serial.print(txString); Serial.println(" ***"); } } void loop() { BLE_Kalibrierung(Waage1,Waage2,Waage3,Waage4); client = server.available(); if (client) { // got client? boolean currentLineIsBlank = true; while (client.connected()) { if (client.available()) { // client data available to read char c = client.read(); // read 1 byte (character) from client // buffer first part of HTTP request in HTTP_req array (string) // leave last element in array as 0 to null terminate string (REQ_BUF_SZ - 1) if (req_index < (REQ_BUF_SZ - 1)) { HTTP_req[req_index] = c; // save HTTP request character req_index++; } // last line of client request is blank and ends with \n // respond to client only after last line received if (c == '\n' && currentLineIsBlank) { // send a standard http response header client.println("HTTP/1.1 200 OK"); // remainder of header follows below, depending on if // web page or XML page is requested // Ajax request - send XML file if (StrContains(HTTP_req, "ajax_inputs")) { // send rest of HTTP header Daten.Time = MilliInSecondandMinutes(millis()); Daten.kraft1 = Waage1.getGewicht(); Daten.kraft2 = Waage2.getGewicht(); Daten.kraft3 = Waage3.getGewicht(); Daten.kraft4 = Waage4.getGewicht(); ADCinSleepMode(); client.println("Content-Type: text/xml"); client.println("Connection: keep-alive"); client.println(); client.print("<?xml version = \"1.0\" ?>"); client.print("<inputs>"); client.print("<kraft>"); client.print(Daten.kraft1); client.print("</kraft>"); client.print("<kraft>"); client.print(Daten.kraft2); client.print("</kraft>"); client.print("<kraft>"); client.print(Daten.kraft3); client.print("</kraft>"); client.print("<kraft>"); client.print(Daten.kraft4); client.print("</kraft>"); client.print("<time>"); client.print(Daten.Time.hours); client.print("</time>"); client.print("<time>"); client.print(Daten.Time.minutes); client.print("</time>"); client.print("<time>"); client.print(Daten.Time.seconds); client.print("</time>"); client.print("<time>"); client.print(Daten.Time.millisec); client.print("</time>"); client.print("<time>"); client.print(Daten.Time.gesamt); client.print("</time>"); client.print("</inputs>"); AnzeigewithSerial(WaagedataincharConverter(Daten)); AnzeigeinSDKartespeichern(WaagedataincharConverter(Daten)); } else { // web page request // send rest of HTTP header client.println("Content-Type: text/html"); client.println("Connection: keep-alive"); client.println(); // send web page webFile = SD.open(file); // open web page file if (webFile) { while (webFile.available()) { client.write(webFile.read()); // send web page to client } webFile.close(); } } // display received HTTP request on serial port //Serial.println(HTTP_req); // reset buffer index and all buffer elements to 0 req_index = 0; StrClear(HTTP_req, REQ_BUF_SZ); break; } // every line of text received from the client ends with \r\n if (c == '\n') { // last character on line of received text // starting new line with next character read currentLineIsBlank = true; } else if (c != '\r') { // a text character was received from client currentLineIsBlank = false; } } // end if (client.available()) } // end while (client.connected()) delay(1); // give the web browser time to receive the data client.stop(); // close the connection } // end if (client) AnzeigewithDisplayLCD(Daten); } void AnzeigewithDisplayLCD(Waagedata mDaten) { display.clearDisplay(); display.setCursor(18, 0); display.print("--:e-Vertical:--"); display.setCursor(0, 12); display.print("1. Waage:\t"); display.print(mDaten.kraft1); display.setCursor(0, 24); display.print("2. Waage:\t"); display.print(mDaten.kraft2); display.setCursor(0, 37); display.print("3. Waage:\t"); display.print(mDaten.kraft3); display.setCursor(0, 50); display.print("4. Waage:\t"); display.print(mDaten.kraft4); display.display(); } void AnzeigewithSerial(charWaagedata mDaten) { Serial.print(mDaten.hours); Serial.print(":"); Serial.print(mDaten.minutes); Serial.print(":"); Serial.print(mDaten.seconds); Serial.print(":"); Serial.print(mDaten.millisec); Serial.print(","); Serial.print(mDaten.kraft1); Serial.print(","); Serial.print(mDaten.kraft2); Serial.print(","); Serial.print(mDaten.kraft3); Serial.print(","); Serial.println(mDaten.kraft4); } void AnzeigeinSDKartespeichern(charWaagedata mDaten) { File file = SD.open(dateiName, FILE_APPEND); if (!file) { Serial.println("Failed to open file for appending"); return; } file.print(mDaten.hours); file.print(":"); file.print(mDaten.minutes);file.print(":"); file.print(mDaten.seconds);file.print(":"); file.print(mDaten.millisec); file.print(","); file.print(mDaten.kraft1); file.print(","); file.print(mDaten.kraft2); file.print(","); file.print(mDaten.kraft3); file.print(","); file.print(mDaten.kraft4);file.print("\n"); file.close(); /* appendFile(SD,dateiName,mhours); appendFile(SD,dateiName, ":" ); appendFile(SD,dateiName,mminutes); appendFile(SD,dateiName, ":" ); appendFile(SD,dateiName,mseconds); appendFile(SD,dateiName, ":" ); appendFile(SD,dateiName,mmillisec); appendFile(SD,dateiName, ":" ); appendFile(SD,savefile,mseconds );appendFile(SD,savefile, ":"); appendFile(SD,savefile,mmillisec );appendFile(SD,savefile, ","); appendFile(SD,savefile, mkraft1);appendFile(SD,savefile, ","); appendFile(SD,savefile, mkraft2);appendFile(SD,savefile, ","); appendFile(SD,savefile, mkraft3);appendFile(SD,savefile, ","); appendFile(SD,savefile, mkraft4);appendFile(SD,savefile, "\n"); */ } Timestempel MilliInSecondandMinutes(int m_millis) { Timestempel Ruckgabe; Ruckgabe.gesamt = m_millis; Ruckgabe.millisec = m_millis % 1000; Ruckgabe.seconds = (m_millis / 1000) % 60; Ruckgabe.minutes = ((m_millis / (1000 * 60)) % 60); Ruckgabe.hours = ((m_millis / (1000 * 60 * 60)) % 24); return Ruckgabe; } char * floatToChar(char * outstr, float value, int places, int minwidth = 0, bool rightjustify = false) { int digit; float tens = 0.1; int tenscount = 0; int i; float tempfloat = value; int c = 0; int charcount = 1; int extra = 0; // make sure we round properly. this could use pow from <math.h>, but doesn't seem worth the import // if this rounding step isn't here, the value 54.321 prints as 54.3209 // calculate rounding term d: 0.5/pow(10,places) float d = 0.5; if (value < 0) d *= -1.0; // divide by ten for each decimal place for (i = 0; i < places; i++) d /= 10.0; // this small addition, combined with truncation will round our values properly tempfloat += d; // first get value tens to be the large power of ten less than value if (value < 0) tempfloat *= -1.0; while ((tens * 10.0) <= tempfloat) { tens *= 10.0; tenscount += 1; } if (tenscount > 0) charcount += tenscount; else charcount += 1; if (value < 0) charcount += 1; charcount += 1 + places; minwidth += 1; // both count the null final character if (minwidth > charcount) { extra = minwidth - charcount; charcount = minwidth; } if (extra > 0 and rightjustify) { for (int i = 0; i < extra; i++) { outstr[c++] = ' '; } } // write out the negative if needed if (value < 0) outstr[c++] = '-'; if (tenscount == 0) outstr[c++] = '0'; for (i = 0; i < tenscount; i++) { digit = (int) (tempfloat / tens); itoa(digit, &outstr[c++], 10); tempfloat = tempfloat - ((float)digit * tens); tens /= 10.0; } // if no places after decimal, stop now and return // otherwise, write the point and continue on if (places > 0) outstr[c++] = '.'; // now write out each decimal place by shifting digits one by one into the ones place and writing the truncated value for (i = 0; i < places; i++) { tempfloat *= 10.0; digit = (int) tempfloat; itoa(digit, &outstr[c++], 10); // once written, subtract off that digit tempfloat = tempfloat - (float) digit; } if (extra > 0 and not rightjustify) { for (int i = 0; i < extra; i++) { outstr[c++] = ' '; } } outstr[c++] = '\0'; return outstr; } charWaagedata WaagedataincharConverter(Waagedata mData) { charWaagedata lokalcharData; /*String sgesamt = String(mData.Time.gesamt); sgesamt.toCharArray(lokalcharData.gesamt,2);*/ itoa(mData.Time.hours,lokalcharData.hours,10); itoa(mData.Time.minutes,lokalcharData.minutes,10); itoa(mData.Time.seconds,lokalcharData.seconds,10); itoa(mData.Time.millisec,lokalcharData.millisec,10); //lokalcharData.gesamt= (char)mData.Time.gesamt; floatToChar(lokalcharData.kraft1, mData.kraft1, 3); floatToChar(lokalcharData.kraft2, mData.kraft2, 3); floatToChar(lokalcharData.kraft3, mData.kraft3, 3); floatToChar(lokalcharData.kraft4, mData.kraft4, 3); return lokalcharData; } void StrClear(char *str, char length) { // sets every element of str to 0 (clears array) for (int i = 0; i < length; i++) { str[i] = 0; } } char StrContains(char *str, char *sfind) { // searches for the string sfind in the string str // returns 1 if string found // returns 0 if string not found char found = 0; char index = 0; char len; len = strlen(str); if (strlen(sfind) > len) { return 0; } while (index < len) { if (str[index] == sfind[found]) { found++; if (strlen(sfind) == found) { return 1; } } else { found = 0; } index++; } return 0; } void ADCinSleepMode() { Waage1.power_down(); Waage2.power_down(); Waage3.power_down(); Waage4.power_down(); delay(100); Waage1.power_up(); Waage2.power_up(); Waage3.power_up(); Waage4.power_up(); } |
Mit Unterstützung von Prof. J. Walter | Sommersemester 2018 |