Hirdetés

Új hozzászólás Aktív témák

  • vargalex

    félisten

    válasz fecske13 #7382 üzenetére

    Szia!

    Szóval, a kód:

    #include <ESP8266WiFi.h>
    #include <Wire.h>
    #include <OneWire.h>
    #include <DallasTemperature.h>
    #include <ESP8266HTTPClient.h>
    #include <time.h>

    #define TEMPERATURE_PRECISION 11
    #define REPORT_INTERVAL 60 // in sec
    #define INTERVAL_CORRECTION 1.01 //1.06001

    //AP definitions
    #define FIRST_SSID "SSID1"
    #define FIRST_PASSWORD "PASS1"
    #define SECOND_SSID "SSID2"
    #define SECOND_PASSWORD "PASS2"
    #define UPDATEURL "http://az.en.szerverem.hu/updatesensor.php"

    #define ONEWIRE_GPIO 2

    #define VCC_ADJUST 1.0

    #define MAXRTCDATACOUNT 50
    #define MINPOSTCOUNT 10
    #define NTPSERVER "time.kfki.hu"


    ADC_MODE(ADC_VCC);

    struct {
    uint32 lastTime;
    int cnt;
    float temperatures[MAXRTCDATACOUNT];
    float battery[MAXRTCDATACOUNT];
    } rtcData;

    // Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
    OneWire oneWire(ONEWIRE_GPIO);

    // Pass our oneWire reference to Dallas Temperature.
    DallasTemperature sensors(&oneWire);

    // device addresses
    DeviceAddress DSAddress;

    // device address in char array
    static char DSAddressStr[18];
    static char *hex = "0123456789ABCDEF";

    int deviceCnt;
    char *ap_ssid = NULL;
    char *ap_password;

    HTTPClient http;

    boolean setSNTPTime(char *NTPServer) {
    unsigned long entry=millis();
    configTime(0,0,NTPServer);
    while (millis()-entry<5000 && time(NULL)<3600) {
    delay(500);
    }
    if (time(NULL)>100) return true;
    else return false;
    }


    void scanWifi() {

    WiFi.mode(WIFI_STA);
    WiFi.disconnect();
    delay(100);
    Serial.println("Scanning for wireless networks");

    // WiFi.scanNetworks will return the number of networks found
    int n = WiFi.scanNetworks();
    Serial.println("scan done");
    if (n == 0)
    Serial.println("no networks found");
    else
    {
    Serial.print(n);
    Serial.println(" networks found");
    ap_ssid = NULL;
    for (int i = 0; i < n; ++i)
    {
    // Print SSID and RSSI for each network found
    Serial.print(i + 1);
    Serial.print(": ");
    Serial.print(WiFi.SSID(i));
    Serial.print(" (");
    Serial.print(WiFi.RSSI(i));
    Serial.print(")");
    Serial.println((WiFi.encryptionType(i) == ENC_TYPE_NONE) ? " " : "*");
    if (WiFi.SSID(i) == FIRST_SSID) {
    ap_ssid = FIRST_SSID;
    ap_password = FIRST_PASSWORD;
    }
    if (WiFi.SSID(i) == SECOND_SSID) {
    ap_ssid = SECOND_SSID;
    ap_password = SECOND_PASSWORD;
    }
    }
    }
    if ( ap_ssid == NULL) {
    Serial.println("Defined SSID-s not found. Resetting.");
    ESP.restart();
    }
    Serial.println("");
    }

    void connect() {
    // Connecting to Wifi.
    Serial.println();

    if (WiFi.SSID() == "") {
    // Never connected, scanning for wireless networks
    scanWifi();
    WiFi.mode(WIFI_OFF);
    WiFi.mode(WIFI_STA);
    Serial.print("Connecting to ");
    Serial.println(ap_ssid);
    WiFi.begin(ap_ssid, ap_password);
    }
    else {
    Serial.print("Connecting to ");
    Serial.println(WiFi.SSID());
    }

    unsigned long wifiConnectStart = millis();

    while (WiFi.status() != WL_CONNECTED) {
    // Check to see if
    if (WiFi.status() == WL_CONNECT_FAILED) {
    Serial.println("Failed to connect to WiFi. Please verify credentials: ");
    scanWifi();
    WiFi.mode(WIFI_OFF);
    WiFi.mode(WIFI_STA);
    Serial.print("Connecting to ");
    Serial.println(ap_ssid);
    WiFi.begin(ap_ssid, ap_password);
    ESP.restart();
    }

    delay(500);
    Serial.print(".");
    // Only try for 5 seconds.
    if (millis() - wifiConnectStart > 15000) {
    Serial.println("Failed to connect to WiFi");
    scanWifi();
    WiFi.mode(WIFI_OFF);
    WiFi.mode(WIFI_STA);
    Serial.print("Connecting to ");
    Serial.println(ap_ssid);
    WiFi.begin(ap_ssid, ap_password);
    ESP.restart();
    }
    }

    Serial.println("");
    Serial.println("WiFi connected");
    Serial.print("IP address: ");
    Serial.println(WiFi.localIP());
    }

    // function to return device address as a String
    String deviceAddressToStr(DeviceAddress deviceAddress)
    {
    String ret = "";
    for (uint8_t i = 0; i < 8; i++)
    {
    // zero pad the address if necessary
    ret = ret + hex[DSAddress[i] / 16];
    ret = ret + hex[DSAddress[i] & 15];
    }
    return ret;
    }

    // getting temperature from DS18B20 sensor
    float getTemperature() {

    float tempC = 150;
    // Start up the library
    sensors.begin();


    if (!sensors.getAddress(DSAddress, 0)) {
    Serial.println("Unable to find address for Device 0");
    }
    else {
    // set the resolution
    sensors.setResolution(DSAddress, TEMPERATURE_PRECISION);

    sensors.requestTemperatures();
    tempC = sensors.getTempC(DSAddress);
    Serial.print("Temp C for device ");
    Serial.print(deviceAddressToStr(DSAddress));
    Serial.print(" ");
    Serial.println(tempC, 4);
    }
    return tempC;
    }

    // POST data as JSON to the server
    bool sendData(DeviceAddress dsAddress) {
    bool ret;
    int i;
    String postStr = "{\"sensorAddress\": \"" + deviceAddressToStr(dsAddress) + "\", \"values\": [";
    for (i=0; i<rtcData.cnt; i++) {
    if (i>0) {
    postStr += ",";
    }
    postStr += "{\"offset\":\"" + String(i-rtcData.cnt+1) + "\", \"temperature\":\"" + String(rtcData.temperatures[i], 3) + "\", \"voltage\":\"" + String(rtcData.battery[i]) +"\"}";
    }
    postStr += "]}";
    if (http.begin(UPDATEURL)) {
    Serial.print("Post string: ");
    Serial.println(postStr);
    http.addHeader("Content-Type", "application/json");
    int httpCode = http.POST(postStr);
    Serial.print("HTTP POST return code: ");
    Serial.println(httpCode); //Print HTTP return code
    if (httpCode>0) {
    ret = true;
    }
    else {
    Serial.print("[HTTP] POST... failed, error: ");
    Serial.println(http.errorToString(httpCode).c_str());
    ret = false;
    }
    http.end();
    }
    else {
    ret = false;
    }
    return ret;
    }

    void setup() {
    unsigned long startTime = 0;
    Serial.begin(115200);
    // Wait for serial to initialize.
    while (!Serial) { }
    Serial.println("");
    Serial.println("Dallas Temperature Sensor Control and post data to server (deep sleep version with RTC memory)");
    Serial.print("Reset reason: ");
    Serial.println(ESP.getResetReason());
    if (ESP.getResetReason() != "Deep-Sleep Wake") {
    Serial.println("Non deep-sleep wake. Clearing RTC data storage.");
    rtcData.cnt = 0;
    rtcData.lastTime = 0;
    ESP.rtcUserMemoryWrite(0, (uint32_t*) &rtcData, sizeof(rtcData));
    scanWifi();
    WiFi.mode(WIFI_OFF);
    WiFi.mode(WIFI_STA);
    Serial.print("Connecting to ");
    Serial.println(ap_ssid);
    WiFi.begin(ap_ssid, ap_password);
    startTime = micros();
    }
    if (ESP.rtcUserMemoryRead(0, (uint32_t*) &rtcData, sizeof(rtcData))) {
    float temp = getTemperature();
    rtcData.cnt++;
    rtcData.temperatures[rtcData.cnt-1] = temp;
    rtcData.battery[rtcData.cnt-1] = ESP.getVcc() * VCC_ADJUST;
    Serial.print("CNT: ");
    Serial.println(rtcData.cnt);
    if (rtcData.cnt>=MINPOSTCOUNT) {
    connect();
    Serial.print("Setting NTP time with server ");
    Serial.print(NTPSERVER);
    while (!setSNTPTime(NTPSERVER)) Serial.print(".");
    Serial.println("");
    uint32 seconds = time(NULL);
    if (seconds != 0) {
    Serial.print("seconds: ");
    Serial.println(seconds);
    Serial.print("rtcData.lastTime: ");
    Serial.println(rtcData.lastTime);
    uint32 waitSecs;
    if (rtcData.lastTime == 0 || rtcData.lastTime+rtcData.cnt*REPORT_INTERVAL< seconds) {
    waitSecs = 0;
    }
    else {
    waitSecs = (rtcData.lastTime+rtcData.cnt*REPORT_INTERVAL) - seconds;
    }
    Serial.print("Waiting ");
    Serial.print(waitSecs);
    Serial.println(" seconds before posting data");
    delay(1000*waitSecs);
    seconds = time(NULL);
    startTime = micros();
    if (sendData(DSAddress)) {
    Serial.print("sendData returned true, setting cnt to 0 and lastTime to ");
    Serial.println(seconds);
    rtcData.cnt=0;
    rtcData.lastTime = seconds;
    }
    }
    else {
    Serial.println("time function returned 0");
    }
    }
    ESP.rtcUserMemoryWrite(0, (uint32_t*) &rtcData, sizeof(rtcData));
    }
    else {
    Serial.println("RTC Memory read failed");
    }
    Serial.print("startTime: ");
    Serial.print(startTime);
    Serial.println(" microseconds");
    Serial.print("Entering to deep sleep for ");
    if (rtcData.cnt+1<MINPOSTCOUNT) {
    Serial.print((REPORT_INTERVAL*1000*1000-(micros()-startTime))*INTERVAL_CORRECTION);
    Serial.print(" microseconds and waking up with ");
    Serial.println("wifi disabled");
    ESP.deepSleep((REPORT_INTERVAL*1000*1000-(micros()-startTime))*INTERVAL_CORRECTION, WAKE_RF_DISABLED);
    }
    else {
    Serial.print(((REPORT_INTERVAL-10)*1000*1000-(micros()-startTime))*INTERVAL_CORRECTION);
    Serial.print(" microseconds and waking up with ");
    Serial.println("wifi on");
    ESP.deepSleep(((REPORT_INTERVAL-10)*1000*1000-(micros()-startTime))*INTERVAL_CORRECTION, WAKE_RF_DEFAULT); //WAKE_NO_RFCAL);
    }
    }

    void loop() {
    // put your main code here, to run repeatedly:
    }

    A lényege: kb. percenként méri a hőmérsékletet és a VCC-t, ezeket tárolja RTC User memóriába. A MINPOSTCOUNT-ban meghatározott ébresztés valamivel korábban történik, hogy NTP-n időt szinkronizáljon, így a POST pontosan 10 percenként tud megtörténni (sajnos a deep sleep időmérése valamiért nem túl pontos). A szervernek JSON-ban küldi az adatokat (sensor address, majd a hőmérséklet/feszültség és offset (aktuális időpillanathoz képest időeltolás percben).
    2 SSID-t és hozzá tartozó jelszavakat definiáltam, mivel 2 helyszínen szeretnék ledobni ilyen szenzorokat. Így a wifi scan-ból tudja majd a kód, hogy melyik látható a 2 közül és ahhoz csatlakozik.
    A percenkénti méréshez wifi bekapcsolása nélkül ébresztem az ESP8266-ot, így kisebb a fogyasztása és néhány ms alatt végez is a méréssel, tárolással. Minden 10. mérésnél (vagy ha valamiért nem tudta POST-olni az adatokat, akkor minden következő mérésnél) wifi bekapcsolásával ébred a korábban említett rövidebb sleep után, csatlakozik a wifi-hez, NTP-n szinkronizál, POST-ol és elrakja RTC memóriába a POST idejét. A következő POST-kor ehhez képest történik a várakozás.

    Képet most nem készítettem az eszközről, de nekem az ESP8266-ok (ESP-12F) nálam ilyen boardra vannak felforrasztva. Ennek a hátoldalán ott a hely az LDO-nak (ahogy írtam, HT7333-at használok). Az LDO-t beforrasztva az előlapon található középső 0 ohm-os ellenállást le kell forrasztani. Így a board VCC lábára kötött feszültség az LDO-n keresztül jut el az ESP8266-ig, azaz annak VCC-jén már 3.3V fog megjelenni. Ennek megfelelően az ESP VCC lábát kötöttem össze a CH_PD-vel (mert ugye az alaplap VCC-jéről a Li-Ion cella feszültségét kapná, ami induláskor kb. 4,2 V). Az ESP VCC lábáról kapja a feszültséget a DS18B20 is, valamint az ESP VCC és GND lába közé a stabil tápellátás érdekében egy 1000 uF-os kondit tettem. A DS18B20 GND lába GND-re, a DATA lába a GPIO2-re van kötve (ez utóbbit konstansként definiáltam a proggiban). Ennyi a bekötés, nincs semmi varázslat.
    Azóta is stabilan megy mindkét példány. Mindenképpen beszámolok, hogy 1 cellával meddig bírja az eszköz.

Új hozzászólás Aktív témák