Keresés

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

  • lajbi30

    csendes tag

    válasz fecske13 #1312 üzenetére

    Kösz! Már olvastam párszor az oldalt. Nem az elképzeléssel van a baj,hanem a megvalósítással.
    Tudom,hogy mit szeretnék,de nem értek a programozáshoz.

  • 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.

    Alex

  • Janos250

    őstag

    válasz fecske13 #8044 üzenetére

    Többféle lap van. Amiken ESP-WROOM-32 van, akkor semmi lényeges különbség nincs köztük.
    Amiben különbözni szoktak pl. hogy hány GND láb van, meg hasonlók, továbbá a lábak mellé írt "név", mert nem mindig egyformán nevezik a lábakat. Ezért én többnyire a GPIO sorszámmal és nem a nevével adom meg a lábakat, hogy ha egy másik lapot választok ki, ne tekintse ismeretlennek a lábak elnevezéseit.

    Hangsúlyozom mégegyszer, hogy ha a képen ki van takarva annak a fém burkolatos százlábúnak a felirata, akkor az bizony többnyire ESP8266, nem 32. Persze az se rossz, de a párszáz Ft különbség ellenére a ESP32 SOKKAL többet tud, ma már nem éri meg ESP8266-ot venni. A 8266 programjai is futnak a 32-n is. A 8266-nak én egyetlen előnyét látom: fizikailag kisebb a kevés lábszám miatt, ezért ha picike helyre kell bepasszírozni, akkor az a 8266-al könnyebben megy.

    [ Szerkesztve ]

    Az amerikaiak $ milliókért fejlesztettek golyóstollat űrbéli használatra. Az oroszok ceruzát használnak. Én meg arduinot.

  • _q

    addikt

    válasz fecske13 #8044 üzenetére

    Ahogy Janos250 is írta hasonló.szinte ugyan az a pin kiosztás eltérő minimálisan Nekem dizájnosabbnak tűnik amit linkeltem, illetve olyat vettem én is így mondhatni tesztelt verzió.

    [ Szerkesztve ]

  • Janos250

    őstag

    válasz fecske13 #8050 üzenetére

    "az egyiknek 8-al több lába van"
    Hú, az sok!
    Most nincs előttem a két lap, de akkor azért itt kell szólni az alábbiakról:
    AZ ESP-WROOM-32 kivezeti azokat a lábakat is, amit mi nem használhatunk, mert az ESP32-nek ezek a lábai a flash memória címzését szolgálják, mi - normál esetben - nem használhatjuk. Ezt egyes lapok kivezetik pinre, mások nem. Lehet ez az oka, de majd egyszer kinyomtatom a két lap képét és átbogarászom.
    Nem kompatibilisek?
    Ha azt értjük a kompatibilitás alatt, hogy ugyanott vannak a kivezetett GPIO-k, akkor messze nem kompatibilisek. Bizony meg kell keresni az adott lapon, hogy az adott GPIO hova van kivezetve.
    Egyébiránt meg teljesen kompatibilisek.

    Az amerikaiak $ milliókért fejlesztettek golyóstollat űrbéli használatra. Az oroszok ceruzát használnak. Én meg arduinot.

  • csubuka

    addikt

    válasz fecske13 #9747 üzenetére

    Jogos, mondjuk a browsercall-t úgy is használom, így az a pénz legalább nem állna sehol. Persze az első időszakban a net nem megoldott, szóval lehet mindenképpen GSM megoldás kell, csak később könnyedén voip-esre kéne, hogy átalakítható legyen. Mondjuk ahogy nézem a kettő megoldás igen különböző, szóval az egyik kifejlesztése nem nagyon segít a másikban semmit.

    (#9748) Janos250: Ez egy ilyen voip szolgáltató. Sima böngészőből is lehet telefonálni meg SMS-t küldeni bejelentkezés után, a számlaegyenleg elhasználódásáig. Ugyanakkor akár a Mobilevoip nevő androidos SIP klienst használva is lehet használni és amíg van netkapcsolat addig olcsó hívásokat kezdeményezni hagyományos vezetékes vagy modil irányba meg SMS-t küldeni.

    [ Szerkesztve ]

  • csubuka

    addikt

    válasz fecske13 #9751 üzenetére

    Ez valóban így van. Ámde, ha egyszer itt a pénz nem állna beragadva, mint egy frissen vett feltöltősön, akkor az a viszonylag drága SMS is elfogadható.

  • Janos250

    őstag

    válasz fecske13 #13611 üzenetére

    De! :)
    Látom, a link már nem él, mert azt a szervert közben leállították. A program valamelyik verziója megvan, majd felteszem valahova, hátha valamikor valakit érdekel. Elég bonyolult, mert sok mindent kell csinálnia, így tutorialnak nem alkalmas.
    Azért írja ki induláskor az árvíztűrő tükörfúrógép szöveget, mert ez az értelmetlen szó tartalmaz minden magyar ékezetes karaktert, így ezzel szoktuk ellenőrizni, hogy minden magyar karakter helyesen jelenik-e meg.
    Amit a programhoz szöveget leírtam, azt ma is tartom. :)

    Az amerikaiak $ milliókért fejlesztettek golyóstollat űrbéli használatra. Az oroszok ceruzát használnak. Én meg arduinot.

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