Prof. J. Walter - Informationstechnik, Mikrocomputertechnik, Digitale Medien Quellcode
Hochschule Karlsruhe Logo Fach: Human Information Technik
Projekt: Platine für E-Vertical
Sommersemester 2018
Burak Deniz Güz
Nahal Fathir Akmad

Quellcode

/*
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