Fully functional code for LÜTR v1.
Dependencies: PM2_Libary Adafruit_GFX BME680
main.cpp
- Committer:
- pfammjur
- Date:
- 2021-05-25
- Revision:
- 18:5019da899a41
- Parent:
- 17:80e441d2b10a
File content as of revision 18:5019da899a41:
/* * Written by Juri Pfammatter 25/5/2021 for use in mbedOS * * Inspired by Neal Horman - http://www.wanlink.com and Adafruit - http://www.adafruit.com */ #include "mbed.h" #include "Adafruit_SSD1306.h" #include "mbed_bme680.h" #include "platform/mbed_thread.h" #include "Servo.h" #include "FastPWM.h" /*Defines BME680*/ #define BME_SCK 13 #define BME_MISO 12 #define BME_MOSI 11 #define BME_CS 10 #define ARRAYLENGTH 60 using namespace std::chrono; //Namespce für printf usw... /* BME680 */ I2C i2c(I2C_SDA, I2C_SCL); //I2C Zuweisung Used inside the BME680 Mbed Lib. BME680 bme680(0x77 << 1); //Object erstellen (<<1 für mbed 8bit Adresse) /* OLED */ DigitalOut myled(LED1); /* an I2C sub-class that provides a constructed default */ class I2CPreInit : public I2C { public: I2CPreInit(PinName sda, PinName scl) : I2C(sda, scl) { frequency(400000); //start(); }; }; I2CPreInit gI2C(I2C_SDA, I2C_SCL); Adafruit_SSD1306_I2c oled(gI2C,D4,0x7A,64,128); /* Futaba Servo S3001 20mm 3kg Analog */ // https://www.modellmarkt24.ch/pi/RC-Elektronik/Servos/Standard-Servo-20mm/futaba-servo-s3001-20mm-3kg-analog.html?gclid=CjwKCAjw3pWDBhB3EiwAV1c5rK_-x_Bt19_wIY-IcS2C-RULXKBtYfY0byxejkZLjASro-EMPBUhrxoCgaQQAvD_BwE // create servo objects Servo servo_S1(PB_2); int servoPeriod_mus = 20000; //Zeitperiode int servoMax = 580, servoMin = 350; //2300: 180 ; 300: 0 //float a = -2.3, b = 810; //Gas -> Rotation //Anpassung an defekten Sensor float a = -23, b = 695; float tempA = 0.8369, tempB = -0.6236; //Temperaturkompensation /* Methodendeklaration */ void servoPos(int pos,int wait1, int wait2); void checkExtreme(float temp, float hum, int press, int voc, bool reset); void setAverage(float temp, float hum, int press, int voc, int arraynr); int getAverageI(int array[]); float getAverageF(float array[]); /* Zeitmanagement */ bool executeMainTask = false; Timer power_button_timer,mode_button_timer, loop_timer; int Ts_ms = 500; //Durchlaufzeit -> 2Hz int mode = 1; //Anzeigemodus: Start auf aktuellen Werten int counter = 0; //Zähler für verschiedene Frequnzen /* Arrays für Mittelwerte*/ float tempAr[ARRAYLENGTH], humAr[ARRAYLENGTH]; int pressAr[ARRAYLENGTH], vocAr[ARRAYLENGTH]; int arrayNr = 0; int firstRound = 0; bool firstLap = true; /* Sonstige Parameter */ bool maxOneTime = true; //identische Position maximal ein Mal einstellen bool resetExtreme = true; //reset float temp, maxTemp, minTemp, hum, maxHum, minHum; int press, maxPress, minPress, voc, maxVoc, minVoc; /* Buttons */ InterruptIn power_button(D6); InterruptIn mode_button(D5); void power_button_fall(); void power_button_rise(); void mode_button_fall(); void mode_button_rise(); /* Setup */ void setup(){ //Setup wird 1 mal durchlaufen loop_timer.start(); power_button.mode(PullUp); //interner PullUp power_button.fall(&power_button_fall); //von 1 auf 0 power_button.rise(&power_button_rise); //von 0 auf 1 mode_button.mode(PullUp); mode_button.fall(&mode_button_fall); mode_button.rise(&mode_button_rise); oled.clearDisplay(); oled.splashCustomLogo(); //Logo Anzeigen lassen oled.display(); thread_sleep_for(1000); set_time(1620477341); //Set RTC time to Wed, 21. April 2021 19:28:30 https://www.epochconverter.com/ thread_sleep_for(1000); oled.clearDisplay(); if (!bme680.begin()) { //begin() startet Sensor: Vorheizen usw... oled.printf("BME680 Begin failed \r\n"); //Fehlermeldung }else{ bme680.performReading(); //Nullwerte abfangen } servoPos(servoMax,1000,1000); //Endpositionen anfahren servoPos(servoMin,1000,1000); } int main() { setup(); while(true) { loop_timer.reset(); //Timer reset oled.setTextCursor(0,0); //Textposition reset if(executeMainTask){ /* Zeit */ time_t seconds = time(NULL); char timebuffer[32]; strftime(timebuffer, 32, "%b %d %Y %H:%M:%S", localtime(&seconds));//Nur Stunde, Minuten, Sekunden auslesen oled.printf("%s", timebuffer); oled.setTextCursor(0,15); //Vertikaler Abstand /* Werte auslesen */ if (bme680.performReading()) { temp = tempA*bme680.getTemperature()+tempB; //Temperaturkompensation hum = bme680.getHumidity(); press = static_cast<int>(bme680.getPressure()/100); voc = static_cast<int>(bme680.getGasResistance()/1000.0); }else{ oled.printf("Failed to perform reading :(\n"); } /* Mittelwerte */ if(((counter%(24*3600/ARRAYLENGTH)==0)&& !firstLap)||((counter%(3600/ARRAYLENGTH)==0)&& firstLap)){ //erste 30min: array füllen; danach alle 30 min einen Wert eintragen setAverage(temp, hum, press, voc, arrayNr); (arrayNr==(ARRAYLENGTH-1))? arrayNr= 0: arrayNr++; } /* Extremwerte */ checkExtreme(temp, hum, press, voc, resetExtreme); /* Anzeige */ switch (mode){ case 1: oled.printf("Aktuellwerte\r\n"); oled.printf("Temperatur: %.2f C\r\n",temp); oled.printf("Luftf.: %.2f %%\r\n",hum); oled.printf("Luftdr.: %d hPa\r\n",press); oled.printf("VOC: %d kOhm\r\n",voc); oled.display(); break; case 2: oled.printf("Mittelwerte\r\n"); oled.printf("Temperatur: %.2f C\r\n",getAverageF(tempAr)); oled.printf("Luftf.: %.2f %%\r\n",getAverageF(humAr)); oled.printf("Luftdr.: %d hPa\r\n",getAverageI(pressAr)); oled.printf("VOC: %d kOhm\r\n",getAverageI(vocAr)); oled.display(); break; case 3: oled.printf("Extremwerte\r\n"); oled.printf("Temp: %.1f %.1f C\r\n",minTemp, maxTemp); oled.printf("Luftf.: %.1f %.1f %%\r\n",minHum, maxHum); oled.printf("Luftd.: %d %d hPa\r\n",minPress, maxPress); oled.printf("VOC: %d %d kOhm\r\n",minVoc, maxVoc); oled.display(); break; } /* Servo */ if(counter%10==0){ //Nur alle 5s Position ändern int output = static_cast<int>(a*(bme680.getGasResistance()/1000.0)+b); if(output>=servoMin && output<=servoMax){ servoPos(output,250,0); maxOneTime = true; }else if(output <= servoMin){ if(maxOneTime){ servoPos(servoMin,250,0); maxOneTime = false; } }else{ if(maxOneTime){ servoPos(servoMax,250,0); maxOneTime = false; } } } /* Timer */ int T_loop_ms = duration_cast<milliseconds>(loop_timer.elapsed_time()).count(); int dT_loop_ms = Ts_ms - T_loop_ms; if(dT_loop_ms>=0 && dT_loop_ms<=Ts_ms)thread_sleep_for(dT_loop_ms); oled.clearDisplay(); (counter==1440000)?counter=0: counter++; //Zähler um 1 erhöhen und nach 720000s wiederholen if(counter==3600){ //Erste Runde um Array zu füllen firstLap = false; } }else{ oled.clearDisplay(); oled.display(); if(maxOneTime){ servoPos(servoMax,Ts_ms,0); maxOneTime = false; } } } } //* Methoden *// /* Servo Position */ void servoPos(int pos,int wait1,int wait2){ servo_S1.Enable(servoMin, servoPeriod_mus); servo_S1.SetPosition(pos); thread_sleep_for(wait1); servo_S1.Disable(); thread_sleep_for(wait2); } /* Power-Buttons */ void power_button_fall() { power_button_timer.reset(); power_button_timer.start(); } void power_button_rise() { int t_button = duration_cast<milliseconds>(power_button_timer.elapsed_time()).count(); power_button_timer.stop(); if(t_button > 30){ resetExtreme = true; executeMainTask = !executeMainTask; } } /* Mode-Buttons */ void mode_button_fall() { mode_button_timer.reset(); mode_button_timer.start(); } void mode_button_rise() { int t_button = duration_cast<milliseconds>(mode_button_timer.elapsed_time()).count(); mode_button_timer.stop(); if(t_button > 30) { (mode!=3) ? mode++ : mode=1; } } /* Mittelwerte */ void setAverage(float temp, float hum, int press, int voc, int arrayNr){ tempAr[arrayNr] = temp; humAr[arrayNr] = hum; pressAr[arrayNr] = press; vocAr[arrayNr] = voc; if(firstRound<ARRAYLENGTH)firstRound++; //Arraylänge für Durchschnitt } int getAverageI(int array[]){ //int als Rückgabewert int sum = 0; for(int j=0; j<firstRound;j++){ if(array[j]!=0)sum+=array[j]; } return sum/firstRound; } float getAverageF(float array[]){ //float als Rückgabewert float sum = 0; for(int j=0; j<firstRound;j++){ if(array[j]!=0)sum+=array[j]; } return sum/firstRound; } /* Extemwerte */ void checkExtreme(float temp, float hum, int press, int voc, bool reset){ if(reset){ //reset minTemp = temp; maxTemp = temp; minHum = hum; maxHum = hum; minPress = press; maxPress = press; minVoc = voc; maxVoc = voc; resetExtreme = false; } if(temp >= maxTemp)maxTemp = temp; if(temp <= minTemp||minTemp <= 1.0)minTemp = temp; if(hum >= maxHum) maxHum = hum; if(hum <= minHum||minHum <= 1.0)minHum = hum; if(press >= maxPress) maxPress = press; if(press <= minPress||minPress <= 1)minPress = press; if(voc >= maxVoc) maxVoc = voc; if(voc <= minVoc||minVoc <= 1)minVoc = voc; }