finalized code of LUTR v1

Dependencies:   PM2_Libary Adafruit_GFX BME680

Committer:
pfammjur
Date:
Mon May 17 12:23:31 2021 +0000
Revision:
16:7536b5d2365c
Parent:
15:d14167e8c555
Child:
17:80e441d2b10a
added average

Who changed what in which revision?

UserRevisionLine numberNew contents of line
pfammjur 15:d14167e8c555 1 /*
pfammjur 15:d14167e8c555 2 * Written by Juri Pfammatter 1/5/2021 for use in mbedOS
pfammjur 15:d14167e8c555 3 *
pfammjur 15:d14167e8c555 4 * Inspired by Neal Horman - http://www.wanlink.com
pfammjur 15:d14167e8c555 5 and Adafruit - http://www.adafruit.com
pfammjur 15:d14167e8c555 6 */
pfammjur 15:d14167e8c555 7
pfammjur 15:d14167e8c555 8 #include "mbed.h"
pfammjur 15:d14167e8c555 9 #include "Adafruit_SSD1306.h"
pfammjur 15:d14167e8c555 10 #include "mbed_bme680.h"
pfammjur 15:d14167e8c555 11 #include "platform/mbed_thread.h"
pfammjur 15:d14167e8c555 12 #include "Servo.h"
pfammjur 15:d14167e8c555 13 #include "FastPWM.h"
pfammjur 15:d14167e8c555 14
pfammjur 15:d14167e8c555 15 /*Defines BME680*/
pfammjur 15:d14167e8c555 16 #define BME_SCK 13
pfammjur 15:d14167e8c555 17 #define BME_MISO 12
pfammjur 15:d14167e8c555 18 #define BME_MOSI 11
pfammjur 15:d14167e8c555 19 #define BME_CS 10
pfammjur 15:d14167e8c555 20
pfammjur 15:d14167e8c555 21
pfammjur 15:d14167e8c555 22 using namespace std::chrono; //Namespce für printf usw...
pfammjur 15:d14167e8c555 23
pfammjur 15:d14167e8c555 24
pfammjur 15:d14167e8c555 25 /* BME680 */
pfammjur 16:7536b5d2365c 26 I2C i2c(I2C_SDA, I2C_SCL); //I2C Zuweisung Used inside the BME680 Mbed Lib.
pfammjur 15:d14167e8c555 27 BME680 bme680(0x77 << 1); //Object erstellen (<<1 für mbed 8bit Adresse)
pfammjur 15:d14167e8c555 28
pfammjur 15:d14167e8c555 29 /* OLED */
pfammjur 15:d14167e8c555 30 DigitalOut myled(LED1);
pfammjur 15:d14167e8c555 31 /* an I2C sub-class that provides a constructed default */
pfammjur 15:d14167e8c555 32 class I2CPreInit : public I2C
pfammjur 15:d14167e8c555 33 {
pfammjur 15:d14167e8c555 34 public:
pfammjur 15:d14167e8c555 35 I2CPreInit(PinName sda, PinName scl) : I2C(sda, scl)
pfammjur 15:d14167e8c555 36 {
pfammjur 15:d14167e8c555 37 frequency(400000);
pfammjur 15:d14167e8c555 38 //start();
pfammjur 15:d14167e8c555 39 };
pfammjur 15:d14167e8c555 40 };
pfammjur 15:d14167e8c555 41
pfammjur 15:d14167e8c555 42 I2CPreInit gI2C(I2C_SDA, I2C_SCL);
pfammjur 15:d14167e8c555 43 Adafruit_SSD1306_I2c oled(gI2C,D4,0x7A,64,128);
pfammjur 15:d14167e8c555 44
pfammjur 15:d14167e8c555 45
pfammjur 15:d14167e8c555 46 /* Futaba Servo S3001 20mm 3kg Analog */
pfammjur 15:d14167e8c555 47 // 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
pfammjur 15:d14167e8c555 48 // create servo objects
pfammjur 15:d14167e8c555 49 Servo servo_S1(PB_2);
pfammjur 15:d14167e8c555 50 int servoPeriod_mus = 20000; //Zeitperiode
pfammjur 15:d14167e8c555 51 int servoMax = 580, servoMin = 350; //2300: 180 ; 300: 0
pfammjur 15:d14167e8c555 52 float a = -2.3, b = 810; //Gas -> Rotation
pfammjur 15:d14167e8c555 53
pfammjur 15:d14167e8c555 54
pfammjur 15:d14167e8c555 55 /* Methodendeklaration */
pfammjur 15:d14167e8c555 56 void servoPos(int pos,int wait1, int wait2);
pfammjur 15:d14167e8c555 57 void checkExtreme(float temp, float hum, int press, int voc, bool reset);
pfammjur 16:7536b5d2365c 58 void setAverage(float temp, float hum, int press, int voc, int arraynr);
pfammjur 16:7536b5d2365c 59 int getAverageI(int array[]);
pfammjur 16:7536b5d2365c 60 float getAverageF(float array[]);
pfammjur 15:d14167e8c555 61
pfammjur 15:d14167e8c555 62 /* Zeitmanagement */
pfammjur 15:d14167e8c555 63 bool executeMainTask = false;
pfammjur 15:d14167e8c555 64 Timer power_button_timer,mode_button_timer, loop_timer;
pfammjur 15:d14167e8c555 65 int Ts_ms = 500; //Durchlaufzeit
pfammjur 15:d14167e8c555 66 int mode = 1;
pfammjur 15:d14167e8c555 67 int counter = 0;
pfammjur 15:d14167e8c555 68
pfammjur 16:7536b5d2365c 69 /* Array für Mittelwerte*/
pfammjur 16:7536b5d2365c 70 float tempAr[30], humAr[30];
pfammjur 16:7536b5d2365c 71 int pressAr[30], vocAr[30];
pfammjur 16:7536b5d2365c 72 int arrayNr = 0;
pfammjur 16:7536b5d2365c 73 int firstThirty = 0;
pfammjur 16:7536b5d2365c 74 bool firstLap = true;
pfammjur 16:7536b5d2365c 75
pfammjur 15:d14167e8c555 76 /* Sonstige Parameter */
pfammjur 15:d14167e8c555 77 bool maxOneTime = true; //identische Position maximal ein mal einstellen
pfammjur 15:d14167e8c555 78 bool resetExtreme = true; //reset
pfammjur 15:d14167e8c555 79 float temp, maxTemp, minTemp, hum, maxHum, minHum;
pfammjur 15:d14167e8c555 80 int press, maxPress, minPress, voc, maxVoc, minVoc;
pfammjur 15:d14167e8c555 81
pfammjur 15:d14167e8c555 82
pfammjur 15:d14167e8c555 83 /* Buttons */
pfammjur 15:d14167e8c555 84 InterruptIn power_button(D6);
pfammjur 15:d14167e8c555 85 InterruptIn mode_button(D5);
pfammjur 15:d14167e8c555 86 void power_button_fall();
pfammjur 15:d14167e8c555 87 void power_button_rise();
pfammjur 15:d14167e8c555 88 void mode_button_fall();
pfammjur 15:d14167e8c555 89 void mode_button_rise();
pfammjur 15:d14167e8c555 90
pfammjur 15:d14167e8c555 91 /* Setup */
pfammjur 15:d14167e8c555 92 void setup(){ //Setup wird 1 mal durchlaufen
pfammjur 15:d14167e8c555 93 loop_timer.start();
pfammjur 15:d14167e8c555 94 power_button.mode(PullUp); //interner PullUp
pfammjur 15:d14167e8c555 95 power_button.fall(&power_button_fall); //von 1 auf 0
pfammjur 15:d14167e8c555 96 power_button.rise(&power_button_rise); //von 0 auf 1
pfammjur 15:d14167e8c555 97 mode_button.mode(PullUp);
pfammjur 15:d14167e8c555 98 mode_button.fall(&mode_button_fall);
pfammjur 15:d14167e8c555 99 mode_button.rise(&mode_button_rise);
pfammjur 15:d14167e8c555 100 oled.clearDisplay();
pfammjur 15:d14167e8c555 101 oled.splashCustomLogo(); //Logo Anzeigen lassen
pfammjur 15:d14167e8c555 102 oled.display();
pfammjur 15:d14167e8c555 103 thread_sleep_for(1000);
pfammjur 16:7536b5d2365c 104 set_time(1620477341); //Set RTC time to Wed, 21. April 2021 19:28:30 https://www.epochconverter.com/
pfammjur 15:d14167e8c555 105 thread_sleep_for(1000);
pfammjur 15:d14167e8c555 106 oled.clearDisplay();
pfammjur 15:d14167e8c555 107 if (!bme680.begin()) { //begin() startet Sensor: Vorheizen usw...
pfammjur 15:d14167e8c555 108 oled.printf("BME680 Begin failed \r\n"); //Fehlermeldung
pfammjur 15:d14167e8c555 109 }
pfammjur 15:d14167e8c555 110 servoPos(servoMax,1000,1000); //Endpositionen anfahren
pfammjur 15:d14167e8c555 111 servoPos(servoMin,1000,1000);
pfammjur 15:d14167e8c555 112
pfammjur 15:d14167e8c555 113
pfammjur 15:d14167e8c555 114 }
pfammjur 15:d14167e8c555 115
pfammjur 15:d14167e8c555 116 int main()
pfammjur 15:d14167e8c555 117 {
pfammjur 15:d14167e8c555 118 setup();
pfammjur 15:d14167e8c555 119
pfammjur 15:d14167e8c555 120 while(true)
pfammjur 15:d14167e8c555 121 {
pfammjur 15:d14167e8c555 122 loop_timer.reset(); //Timer reset
pfammjur 15:d14167e8c555 123 oled.setTextCursor(0,0); //Textposition reset
pfammjur 15:d14167e8c555 124
pfammjur 15:d14167e8c555 125 if(executeMainTask){
pfammjur 15:d14167e8c555 126
pfammjur 15:d14167e8c555 127 /* Zeit */
pfammjur 15:d14167e8c555 128 time_t seconds = time(NULL);
pfammjur 15:d14167e8c555 129 char timebuffer[32];
pfammjur 15:d14167e8c555 130 strftime(timebuffer, 32, "%b %d %Y %H:%M:%S", localtime(&seconds));//Nur Stunde, Minuten, Sekunden auslesen
pfammjur 15:d14167e8c555 131 oled.printf("%s", timebuffer);
pfammjur 15:d14167e8c555 132
pfammjur 15:d14167e8c555 133 oled.setTextCursor(0,15); //Vertikaler Abstand
pfammjur 15:d14167e8c555 134
pfammjur 15:d14167e8c555 135 /* Werte auslesen */
pfammjur 15:d14167e8c555 136 if (bme680.performReading()) {
pfammjur 15:d14167e8c555 137 temp = bme680.getTemperature()-4.0;
pfammjur 15:d14167e8c555 138 hum = bme680.getHumidity();
pfammjur 15:d14167e8c555 139 press = static_cast<int>(bme680.getPressure()/100);
pfammjur 15:d14167e8c555 140 voc = static_cast<int>(bme680.getGasResistance()/1000.0);
pfammjur 15:d14167e8c555 141 }else{
pfammjur 15:d14167e8c555 142 oled.printf("Failed to perform reading :(\n");
pfammjur 15:d14167e8c555 143 }
pfammjur 16:7536b5d2365c 144 /* Mittelwerte */
pfammjur 16:7536b5d2365c 145 if(counter%3600==0||((counter%120==0)&& firstLap)){ //erste 30min: 1 mal in der Minute; danach alle 30 min
pfammjur 16:7536b5d2365c 146 setAverage(temp, hum, press, voc, arrayNr);
pfammjur 16:7536b5d2365c 147 (arrayNr==29)? arrayNr= 0: arrayNr++;
pfammjur 16:7536b5d2365c 148 }
pfammjur 15:d14167e8c555 149 /* Extremwerte */
pfammjur 15:d14167e8c555 150 checkExtreme(temp, hum, press, voc, resetExtreme);
pfammjur 15:d14167e8c555 151
pfammjur 15:d14167e8c555 152 /* Anzeige */
pfammjur 15:d14167e8c555 153 switch (mode){
pfammjur 16:7536b5d2365c 154 case 1: oled.printf("Aktuellwerte\r\n");
pfammjur 16:7536b5d2365c 155 oled.printf("Temperatur: %.2f C\r\n",temp);
pfammjur 15:d14167e8c555 156 oled.printf("Luftf.: %.2f %%\r\n",hum);
pfammjur 15:d14167e8c555 157 oled.printf("Luftdr.: %d hPa\r\n",press);
pfammjur 15:d14167e8c555 158 oled.printf("VOC: %d kOhm\r\n",voc);
pfammjur 15:d14167e8c555 159 oled.display();
pfammjur 15:d14167e8c555 160 break;
pfammjur 15:d14167e8c555 161
pfammjur 16:7536b5d2365c 162 case 2: oled.printf("Mittelwerte\r\n");
pfammjur 16:7536b5d2365c 163 oled.printf("Temperatur: %.2f C\r\n",getAverageF(tempAr));
pfammjur 16:7536b5d2365c 164 oled.printf("Luftf.: %.2f %%\r\n",getAverageF(humAr));
pfammjur 16:7536b5d2365c 165 oled.printf("Luftdr.: %d hPa\r\n",getAverageI(pressAr));
pfammjur 16:7536b5d2365c 166 oled.printf("VOC: %d kOhm\r\n",getAverageI(vocAr));
pfammjur 16:7536b5d2365c 167 oled.printf("count: %d, fT: %d",counter,firstThirty);
pfammjur 15:d14167e8c555 168 oled.display();
pfammjur 15:d14167e8c555 169 break;
pfammjur 15:d14167e8c555 170
pfammjur 16:7536b5d2365c 171 case 3: oled.printf("Extremwerte\r\n");
pfammjur 16:7536b5d2365c 172 oled.printf("Temp: %.1f %.1f C\r\n",minTemp, maxTemp);
pfammjur 15:d14167e8c555 173 oled.printf("Luftf.: %.1f %.1f %%\r\n",minHum, maxHum);
pfammjur 15:d14167e8c555 174 oled.printf("Luftd.: %d %d hPa\r\n",minPress, maxPress);
pfammjur 15:d14167e8c555 175 oled.printf("VOC: %d %d kOhm\r\n",minVoc, maxVoc);
pfammjur 15:d14167e8c555 176 oled.display();
pfammjur 15:d14167e8c555 177 break;
pfammjur 15:d14167e8c555 178 }
pfammjur 15:d14167e8c555 179
pfammjur 15:d14167e8c555 180 /* Servo */
pfammjur 15:d14167e8c555 181 if(counter%10==0){
pfammjur 15:d14167e8c555 182 int output = static_cast<int>(a*(bme680.getGasResistance()/1000.0)+b);
pfammjur 15:d14167e8c555 183 if(output>=servoMin && output<=servoMax){
pfammjur 15:d14167e8c555 184 servoPos(output,250,0);
pfammjur 15:d14167e8c555 185 maxOneTime = true;
pfammjur 15:d14167e8c555 186 }else if(output <= servoMin){
pfammjur 15:d14167e8c555 187 if(maxOneTime){
pfammjur 15:d14167e8c555 188 servoPos(servoMin,250,0);
pfammjur 15:d14167e8c555 189 maxOneTime = false;
pfammjur 15:d14167e8c555 190 }
pfammjur 15:d14167e8c555 191 }else{
pfammjur 15:d14167e8c555 192 if(maxOneTime){
pfammjur 15:d14167e8c555 193 servoPos(servoMax,250,0);
pfammjur 15:d14167e8c555 194 maxOneTime = false;
pfammjur 15:d14167e8c555 195 }
pfammjur 15:d14167e8c555 196 }
pfammjur 15:d14167e8c555 197 }
pfammjur 15:d14167e8c555 198
pfammjur 15:d14167e8c555 199 /* Timer */
pfammjur 15:d14167e8c555 200 int T_loop_ms = duration_cast<milliseconds>(loop_timer.elapsed_time()).count();
pfammjur 15:d14167e8c555 201 int dT_loop_ms = Ts_ms - T_loop_ms;
pfammjur 15:d14167e8c555 202 if(dT_loop_ms>=0 && dT_loop_ms<=Ts_ms)thread_sleep_for(dT_loop_ms);
pfammjur 15:d14167e8c555 203 oled.clearDisplay();
pfammjur 16:7536b5d2365c 204 if(counter==3600){
pfammjur 16:7536b5d2365c 205 counter = 0;
pfammjur 16:7536b5d2365c 206 firstLap = false;
pfammjur 16:7536b5d2365c 207 }else{
pfammjur 16:7536b5d2365c 208 counter++;
pfammjur 16:7536b5d2365c 209 }
pfammjur 15:d14167e8c555 210
pfammjur 15:d14167e8c555 211 }else{
pfammjur 15:d14167e8c555 212 oled.clearDisplay();
pfammjur 15:d14167e8c555 213 oled.display();
pfammjur 15:d14167e8c555 214 servoPos(servoMax,Ts_ms,0);
pfammjur 15:d14167e8c555 215 }
pfammjur 15:d14167e8c555 216 }
pfammjur 15:d14167e8c555 217 }
pfammjur 15:d14167e8c555 218
pfammjur 15:d14167e8c555 219 //* Methoden *//
pfammjur 15:d14167e8c555 220 /* Servo Position */
pfammjur 15:d14167e8c555 221 void servoPos(int pos,int wait1,int wait2){
pfammjur 15:d14167e8c555 222 servo_S1.Enable(servoMin, servoPeriod_mus);
pfammjur 15:d14167e8c555 223 servo_S1.SetPosition(pos);
pfammjur 15:d14167e8c555 224 thread_sleep_for(wait1);
pfammjur 15:d14167e8c555 225 servo_S1.Disable();
pfammjur 15:d14167e8c555 226 thread_sleep_for(wait2);
pfammjur 15:d14167e8c555 227 }
pfammjur 15:d14167e8c555 228 /* Power-Buttons */
pfammjur 15:d14167e8c555 229 void power_button_fall()
pfammjur 15:d14167e8c555 230 {
pfammjur 15:d14167e8c555 231 power_button_timer.reset();
pfammjur 15:d14167e8c555 232 power_button_timer.start();
pfammjur 15:d14167e8c555 233 }
pfammjur 15:d14167e8c555 234
pfammjur 15:d14167e8c555 235 void power_button_rise()
pfammjur 15:d14167e8c555 236 {
pfammjur 15:d14167e8c555 237 int t_button = duration_cast<milliseconds>(power_button_timer.elapsed_time()).count();
pfammjur 15:d14167e8c555 238 power_button_timer.stop();
pfammjur 15:d14167e8c555 239 if(t_button > 30){
pfammjur 15:d14167e8c555 240 resetExtreme = true;
pfammjur 15:d14167e8c555 241 executeMainTask = !executeMainTask;
pfammjur 15:d14167e8c555 242 }
pfammjur 15:d14167e8c555 243 }
pfammjur 15:d14167e8c555 244 /* Mode-Buttons */
pfammjur 15:d14167e8c555 245 void mode_button_fall()
pfammjur 15:d14167e8c555 246 {
pfammjur 15:d14167e8c555 247 mode_button_timer.reset();
pfammjur 15:d14167e8c555 248 mode_button_timer.start();
pfammjur 15:d14167e8c555 249 }
pfammjur 15:d14167e8c555 250
pfammjur 15:d14167e8c555 251 void mode_button_rise()
pfammjur 15:d14167e8c555 252 {
pfammjur 15:d14167e8c555 253 int t_button = duration_cast<milliseconds>(mode_button_timer.elapsed_time()).count();
pfammjur 15:d14167e8c555 254 mode_button_timer.stop();
pfammjur 15:d14167e8c555 255 if(t_button > 30) {
pfammjur 15:d14167e8c555 256 (mode!=3) ? mode++ : mode=1;
pfammjur 15:d14167e8c555 257 }
pfammjur 15:d14167e8c555 258 }
pfammjur 16:7536b5d2365c 259
pfammjur 16:7536b5d2365c 260 /* Mittelwerte */
pfammjur 16:7536b5d2365c 261 void setAverage(float temp, float hum, int press, int voc, int arrayNr){
pfammjur 16:7536b5d2365c 262 tempAr[arrayNr] = temp;
pfammjur 16:7536b5d2365c 263 humAr[arrayNr] = hum;
pfammjur 16:7536b5d2365c 264 pressAr[arrayNr] = press;
pfammjur 16:7536b5d2365c 265 vocAr[arrayNr] = voc;
pfammjur 16:7536b5d2365c 266 if(firstThirty<29)firstThirty++;
pfammjur 16:7536b5d2365c 267 }
pfammjur 16:7536b5d2365c 268 int getAverageI(int array[]){
pfammjur 16:7536b5d2365c 269 int sum = 0;
pfammjur 16:7536b5d2365c 270 for(int j=0; j<firstThirty;j++){
pfammjur 16:7536b5d2365c 271 sum+=array[j];
pfammjur 16:7536b5d2365c 272 }
pfammjur 16:7536b5d2365c 273 return sum/(firstThirty+1);
pfammjur 16:7536b5d2365c 274 }
pfammjur 16:7536b5d2365c 275
pfammjur 16:7536b5d2365c 276 float getAverageF(float array[]){
pfammjur 16:7536b5d2365c 277 float sum = 0;
pfammjur 16:7536b5d2365c 278 for(int j=0; j<firstThirty;j++){
pfammjur 16:7536b5d2365c 279 sum+=array[j];
pfammjur 16:7536b5d2365c 280 }
pfammjur 16:7536b5d2365c 281 return sum/firstThirty;
pfammjur 16:7536b5d2365c 282 }
pfammjur 16:7536b5d2365c 283
pfammjur 15:d14167e8c555 284 /* Extemwerte */
pfammjur 15:d14167e8c555 285 void checkExtreme(float temp, float hum, int press, int voc, bool reset){
pfammjur 15:d14167e8c555 286 if(reset){ //reset
pfammjur 15:d14167e8c555 287 minTemp = temp;
pfammjur 15:d14167e8c555 288 maxTemp = temp;
pfammjur 15:d14167e8c555 289 minHum = hum;
pfammjur 15:d14167e8c555 290 maxHum = hum;
pfammjur 15:d14167e8c555 291 minPress = press;
pfammjur 15:d14167e8c555 292 maxPress = press;
pfammjur 15:d14167e8c555 293 minVoc = voc;
pfammjur 15:d14167e8c555 294 maxVoc = voc;
pfammjur 15:d14167e8c555 295 resetExtreme = false;
pfammjur 15:d14167e8c555 296 }
pfammjur 15:d14167e8c555 297 if(temp >= maxTemp)maxTemp = temp;
pfammjur 15:d14167e8c555 298 if(temp <= minTemp||minTemp <= 1.0)minTemp = temp;
pfammjur 15:d14167e8c555 299 if(hum >= maxHum) maxHum = hum;
pfammjur 15:d14167e8c555 300 if(hum <= minHum||minHum <= 1.0)minHum = hum;
pfammjur 15:d14167e8c555 301 if(press >= maxPress) maxPress = press;
pfammjur 15:d14167e8c555 302 if(press <= minPress||minPress <= 1)minPress = press;
pfammjur 15:d14167e8c555 303 if(voc >= maxVoc) maxVoc = voc;
pfammjur 15:d14167e8c555 304 if(voc <= minVoc||minVoc <= 1)minVoc = voc;
pfammjur 15:d14167e8c555 305 }