Weather station project updated display and sensors
Dependencies: BH1750 BMP280 DS1820 HMC5983 Helios MAX17043 MPU6050 SHTx SSD1306_I2C A4988_stepper mbed
Fork of weather_station_project by
main.cpp
- Committer:
- daniel_davvid
- Date:
- 2018-07-04
- Revision:
- 3:44517d2520e1
- Parent:
- 2:bc1c1f395e9a
File content as of revision 3:44517d2520e1:
#include "mbed.h" #define DONT_MOVE 0 #define UPDATE_RTC_TIME 0 #define RTC_TIME 1530462446 #define DISPLAY_INTERVAL 0.5f #define SUN_POS_INTERVAL 10// one minute for sun position update using // the Helios algorithm #define PLATFORM_POSITION_POLL_INTERVAL 1 // read platform position sensors #define WEATHER_STATE_UPDATE_INTERVAL 1 #ifndef M_PI #define M_PI 3.1415926535897932384626433832795028841971693993751058209749445923078164f #endif // DS1820 temp sens pin #define MAX_PROBES 16 #define DATA_PIN A1 //#define MULTIPLE_PROBES #include "BH1750.h" //Light sensor lib #include "BMP280.h" //Pressure sensor lib #include "DS1820.h" //Temp sensor lib (One wire) #include "Helios.h" //Sun tracking algorithm #include "HMC5983.h" //Compass lib #include "MAX17043.h" //Fuel gauge sens lib #include "MPU6050.h" //Accelerometer sensor lib #include "SHTx/sht15.hpp" //Humidity sens lib #include "SSD1306.h" //Display lib #include "stepper.h" //Stepping motor lib. Serial pc(USBTX, USBRX); //Serial pi(D1, D0); //Digital pins DigitalIn maxAngleLimit(PC_8); DigitalIn minAngleLimit(PC_6); DigitalOut swPi(PC_5); DigitalIn pir(PB_12); //Analog pins AnalogIn waterLevel(A2); AnalogIn crtConsumption(A3); // Stepper motor setup stepper stpCirc(PA_12, NC, NC, NC, PB_1, PB_2); stepper stpAngle(PA_11, NC, NC, NC, PB_14, PB_15); //DS1820 setup DS1820* probe[MAX_PROBES]; //Helios algorithm Helios sun; // I2C communication setup I2C i2c1(D14, D15); I2C i2c2(D3, D6); //I2C i2c3(D5, D7); // Maybe change the format SHTx::SHT15 sht(D5, D7); //I2C 1 sensors BH1750 bh(i2c1); BMP280 bmp(i2c1); HMC5983 compass(i2c1); MAX17043 fuelGauge(i2c1); SSD1306 lcd1(&i2c1, 0x78); //I2C 2 sensors SSD1306 lcd2(&i2c2, 0x78); MPU6050 mpu(i2c2); // Timers Timer sunPosUpdateTimer; Timer platformPositionPollTimer; Timer platformRotateTimer; Timer panelTiltTimer; Timer pirPollTimer; Timer weatherStateUpdateTimer; Timer displayTimer; // platform rotate & panel tilt // timer intervals float platformRotateInterval; float panelTiltInterval; // Accelerometer readings Vector scaledAccel; float vertG; // Z axis component of the g float accelDesiredAngle, accelActualAngle; //Compass float compassDesiredAngle, compassActualAngle; // PIR state variable and update interval bool pirDetectionOccured = false; // 60 seconds warm-up for first update int pirUpdateInterval = 60; // LCD displays current shown page int crtPage = 0; // Auxiliary variables for RTC time // readings time_t seconds; char buffer[32]; //Function forward declarations void init(); // setup all devices float compassAngleDiff(float a, float b); // compute angle difference between // the compass read angle and the // desired angle float accelAngleDiff(float a, float b); int getWaterLevel(); // read the water level sensor void updatePirState(); // read the PIR state and update // state variable float getCrtConsumption(); // read the current sensor int main() { //Sensor variable names float lightIntensity; float bmpTemp, pressure; float humidity, shtTemp; float crtConsumption; float VCell, SOC; float temperature; int maxAngle, minAngle; // initialize all devices init(); while (1) { //Helios if (sunPosUpdateTimer.read() > SUN_POS_INTERVAL) { seconds = time(NULL); strftime(buffer, 32, "%H:%M:%S", localtime(&seconds)); sun.updatePosition(); compassDesiredAngle = sun.azimuth(); accelDesiredAngle = sun.elevation(); } if (pirPollTimer.read() > pirUpdateInterval) { pirPollTimer.reset(); pirUpdateInterval = 1; updatePirState(); } if (platformPositionPollTimer.read() > PLATFORM_POSITION_POLL_INTERVAL) { platformPositionPollTimer.reset(); // read compass compassActualAngle = 360-compass.read(); // read accelerometer scaledAccel = mpu.readScaledAccel(); vertG = scaledAccel.ZAxis; vertG = vertG > 2.0f ? 3.9f - vertG : vertG; vertG = vertG < 1.0f ? vertG : 1.0f; vertG = vertG > -1.0f ? vertG : -1.0f; accelActualAngle = acos(vertG)/M_PI*180.0f; } if (weatherStateUpdateTimer.read() > WEATHER_STATE_UPDATE_INTERVAL) { weatherStateUpdateTimer.reset(); //DS1820 sensor probe[0]->convertTemperature(true, DS1820::all_devices); for (int i = 0; i<1; i++) pc.printf("Device %d returns %3.1foC\r\n", i, probe[i]->temperature()); //SHT15 sht.update(); sht.setScale(false); //Sensor data to variables lightIntensity = bh.lux()/1.2f; bmpTemp = bmp.getTemperature(); pressure = bmp.getPressure(); shtTemp = sht.getTemperature(); humidity = sht.getHumidity(); crtConsumption = getCrtConsumption()*1000; probe[0]->convertTemperature(true, DS1820::all_devices); temperature = probe[0]->temperature(); VCell = fuelGauge.getFloatVCell(); SOC = fuelGauge.getFloatSOC(); maxAngle = maxAngleLimit.read(); minAngle = minAngleLimit.read(); azimuth = sun.azimuth(); elevation = sun.elevation(); } if (platformRotateTimer.read() > platformRotateInterval) { platformRotateTimer.reset(); // rotate the platform to reach the desired compass // indication float angleDiff = compassAngleDiff(compassActualAngle, compassDesiredAngle); if (abs(angleDiff) > 5) { if (!DONT_MOVE) { if (angleDiff > 0) { stpCirc.step(0, 1, 30000); } else { stpCirc.step(0, 0, 30000); } } } // change the rotate interval according to angle difference // for large differences, make the update interval shorter if (abs(angleDiff) > 10) { platformRotateInterval = 0.1f; } else { platformRotateInterval = 1.0f; } } if (panelTiltTimer.read() > panelTiltInterval) { panelTiltTimer.reset(); // tilt the panel to reach the desired accelerometer // indication float angleDiff = accelAngleDiff(accelActualAngle, accelDesiredAngle); if (abs(angleDiff) > 2) { if (!DONT_MOVE) { if (angleDiff > 0 && !maxAngleLimit.read()) { stpAngle.step(0, 1, 30000); } else if (!minAngleLimit.read()) { stpAngle.step(0, 0, 30000); } } } // change the rotate interval according to angle difference // for large differences, make the update interval shorter if (abs(angleDiff) > 5) { panelTiltInterval = 0.1f; } else { panelTiltInterval = 1.0f; } } if (displayTimer.read() > DISPLAY_INTERVAL) { displayTimer.reset(); pc.printf("UTC time is: %s\n", buffer); pc.printf("Sun azimuth: %.2f, elevation: %.2f\n", sun.azimuth(), sun.elevation()); pc.printf("Vcell: %.2f\n", VCell); pc.printf("Battery: %.2f\n", SOC); pc.printf("Temperature [ %3.2f C ]\r\n", shtTemp); pc.printf("Humdity [ %3.2f %% ]\r\n\n", humidity); pc.printf("Compass: %2.3f\n", compassActualAngle); pc.printf("Vertical angle: %1.3f\n", accelActualAngle); pc.printf("Intensity: %5.2f lux\n", lightIntensity); pc.printf("Temp = %f\t Pres = %f\n", bmpTemp,pressure); if (crtPage == 0) { lcd1.setPageAddress(0,0); lcd1.setColumnAddress(0,127); lcd1.printf("Compass: %3.0f", compassActualAngle); //lcd.printf("Difference: %f\n", compassAngleDiff(compassActualAngle, compassDesiredAngle)); lcd1.setPageAddress(1,1); lcd1.setColumnAddress(0,127); lcd1.printf("Angle: %2.0f", accelActualAngle); lcd1.setPageAddress(2,2); lcd1.setColumnAddress(0,127); lcd1.printf("LUX: %4.0f", lightIntensity); lcd1.setPageAddress(3,3); lcd1.setColumnAddress(0,127); lcd1.printf("Temp: %.1f", bmpTemp); lcd1.setPageAddress(4,4); lcd1.setColumnAddress(0,127); lcd1.printf("Press: %4.f", pressure); lcd1.setPageAddress(5,5); lcd1.setColumnAddress(0,127); lcd1.printf("Max: %d", maxAngle); lcd1.setPageAddress(6,6); lcd1.setColumnAddress(0,127); lcd1.printf("Min: %d", minAngle); lcd1.setPageAddress(7,7); lcd1.setColumnAddress(0,127); lcd1.printf("PIR: %s", pirDetectionOccured ? "DETECTED" : "NOTHING "); lcd2.setPageAddress(0,0); lcd2.setColumnAddress(0,127); lcd2.printf("AZMT: %.2f", azimuth); lcd2.setPageAddress(1,1); lcd2.setColumnAddress(0,127); lcd2.printf("ELV: %.2f", elevation); //MAXI17043 lcd2.setPageAddress(2,2); lcd2.setColumnAddress(0,127); lcd2.printf("Vcell: %.2f\n", VCell); lcd2.setPageAddress(3,3); lcd2.setColumnAddress(0,127); lcd2.printf("Battery: %.2f\n",SOC); //SHT15 lcd2.setPageAddress(4,4); lcd2.setColumnAddress(0,127); lcd2.printf("Temp: %3.2f C", shtTemp); lcd2.setPageAddress(5,5); lcd2.setColumnAddress(0,127); lcd2.printf("Hum: %3.2f%%", humidity); lcd2.setPageAddress(6,6); lcd2.setColumnAddress(0,127); lcd2.printf("Crt: %03.1fmA", crtConsumption); lcd2.setPageAddress(7,7); lcd2.setColumnAddress(0,127); lcd2.printf("Temp %2.1f C",temperature); } else { } crtPage = (crtPage + 1) & 1; } } } void init() { maxAngleLimit.mode(PullUp); minAngleLimit.mode(PullUp); if (UPDATE_RTC_TIME) { set_time(RTC_TIME); } // Stepper drivers setup if (DONT_MOVE) { stpAngle.disable(); stpCirc.disable(); } else { stpAngle.enable(); stpCirc.enable(); } swPi = 0; //SHT15 setup sht.setOTPReload(false); sht.setResolution(true); // DS1820 setup int num_devices = 0; while(DS1820::unassignedProbe(DATA_PIN)) { probe[num_devices] = new DS1820(DATA_PIN); num_devices++; if (num_devices == MAX_PROBES) break; } //MPU setup while(!mpu.begin(MPU6050_SCALE_2000DPS, MPU6050_RANGE_2G)) { pc.printf("Could not find a valid MPU6050 sensor, check wiring!\n"); wait(0.5); } mpu.calibrateGyro(); mpu.setThreshold(3); //BMP setup bmp.initialize(); //BH setup bh.init(); // compass.init(); compassDesiredAngle = 0.0f; accelDesiredAngle = 45.0f; platformRotateInterval = 0.1f; panelTiltInterval = 0.1f; //Timers Start platformRotateTimer.start(); panelTiltTimer.start(); weatherStateUpdateTimer.start(); displayTimer.start(); platformPositionPollTimer.start(); pirPollTimer.start(); sunPosUpdateTimer.start(); } float accelAngleDiff(float a, float b) { float diff = a - b; return diff; } float compassAngleDiff(float a, float b) { float diff = a - b; if (diff > 180) diff -= 360; if (diff < -180) diff += 360; return diff; } int getWaterLevel(){ float value; value = waterLevel.read() *1000; if (value<=150) { value=0; } else if (value>150 && value<=210) { value=1/4; } else if (value>210 && value<=250) { value=1/2; } else if (value>250 && value<=350) { value=3/4;; } else if (value>350) { value=1; } value=value*100; //final data in x% return value; } float getCrtConsumption(){ //VOUT=Vcc/2+i*VCC/36.7 //i=36.7*Vout/Vcc-18.3 float result = 36.7f * crtConsumption.read() - 18.3f; result = result < 0 ? 0.0f : result; return result; } void updatePirState() { pirDetectionOccured = pir.read() != 0; }