Автономное питание для ickra js

Тема в разделе "Iskra JS, Espruino, Йодо", создана пользователем griefman, 10 апр 2026.

  1. griefman

    griefman Нерд

    Провел эксперимент. Подключил устройство к компьютеру, отключил у него сеть. Зашел на удаленный сервер с ноута - данные устройство продолжает передавать.
     
  2. parovoZZ

    parovoZZ Гуру

    Это значит, что где то стоит nat.
     
  3. griefman

    griefman Нерд

    И где подмена? ip 79.ххх.ххх.ххх - компьютер, ip 31.ххх.ххх.ххх - роутер с мегафоновским USB-модемом.
     
  4. parovoZZ

    parovoZZ Гуру

    отличие шлюза от nat в том, что шлюз инкапсулирует ip адрес в пакет и декрементирует ttl, а nat подменяет адрес и таблицу подмен держит в себе. Т.е. если пакет-запрос ушёл через один шлюз, то пакет-ответ может прийти через другой шлюз. С nat такое не работает.
    Какое решение проблемы? Назначить компьютеру тот интернет ip адрес, какой выделен. Но проблема в том, что тогда все другие устройства должны будут ходит в интернет через этот же компьютер. Если больше нет выделенных интернет ip адресов (маска 32), то тогда данный компьютер должен превратиться в nat.
     
  5. griefman

    griefman Нерд

    Я ничего в этом не понимаю. В чем ваша мысль? В том, что отправка данных происходит через компьютер минуя модуль wifi на плате и роутер?

    Для пояснения: компьютер работает от домашней сети, а роутер от мегафоновского USB-модема, а плата залогинена на роутер.
     
    Последнее редактирование: 18 апр 2026
  6. ZAZ-965

    ZAZ-965 Гуру

    @griefman, а такой эксперимент - рабочее устройство временно отключить от компьютера и через минуту включить его вновь - работоспособность останется?
    Какой IDE пользуетесь - Native application, Chrome extensions или Web IDE?
    Какой пункт выбран в Save on Send?
    SaveOnSend.gif
     
  7. griefman

    griefman Нерд

    Устройство начинает работать в любое время, как только подключается у компьютеру, даже если компьютер включен, а ОС не загружена.

    Используется Espurino Web IDE. Скрипт записан во flash.
     
    Последнее редактирование: 18 апр 2026
  8. parovoZZ

    parovoZZ Гуру

    это не моя мысль. Так работает NAT в роутере. Единственное назначение роутера - обеспечить выход в открытую ("опасную") сеть из закрытой ("безопасной").
    Мало того, если IP адрес не арендован, то через него выходят сотни других пользователей. Провайдеру так гораздо дешевле. и нет никакой гарантии, что через месяц этот адрес не сменится на какой-то другой. Ну и, разумеется, зайти к себе через этот адрес также невозможно - все входящие соединения провайдер блокирует, т.к. понятия не имеет. для кого они.
     
  9. griefman

    griefman Нерд

    Из вашего ответа я понял как дешевле провайдеру жонглировать адресами и что подмена происходит именно в роутере. Я только никак не пойму как это влияет на мою ситуацию, если мне все равно с какого ip придут данные, главное чтобы они пришли.
     
  10. Ariadna-on-Line

    Ariadna-on-Line Гуру

    После вашего упоминания - Радиокот прекратил работу ((((
    Я в этих делах с серверами и IP адресами - ни бум-бум. Так что здесь я пасс.

    ПС. Решите проблему - напишите. Форумы для того и даны - чтобы ВСЕМ учиться на ошибках каждого.
     
    Последнее редактирование: 19 апр 2026
  11. Ariadna-on-Line

    Ariadna-on-Line Гуру

    Судя по вашим словам - вы подключаете Ардуину к USB компа, и отключаете LAN кабель между компом и роутером, и передача ИДЕТ. Значит Wi-Fi канал между Ардуиной и роутером - работает ??? А если запитаете Ардуину опять же к USB компа но кабелем без сигнальных линий - то передача не работает. Тяжелый случай. В компе нет встроенного Wi-Fi устройства, которое вы не замечаете, но которое держит связь с роутером, даже когда вы выдёргиваете LAN кабель ? Ну и опять же - может кабель без сигнальных линий тоже паскудит питание !?
     
    Последнее редактирование: 19 апр 2026
  12. griefman

    griefman Нерд

    Я подключаю IskraJS к компьютеру по USB-кабелю, никакого LAN нет, сигнал на второй роутер идет через модуль wifi на плате , компьютер подключен к другому роутеру.
     
    Последнее редактирование: 19 апр 2026
  13. parovoZZ

    parovoZZ Гуру

    Это значит, что в искра js стоит что то очень старое, что без резистора на сигнальных жилах не включает питание. Надо подавать через внешние контакты.
     
    Ariadna-on-Line нравится это.
  14. ivan_alexoff

    ivan_alexoff Гик

    это значит - см. ответ #2. Три страницы гаданий без схемы, конкретных названий модулей, кода сидеть и гадать что там ТС наваял
     
  15. griefman

    griefman Нерд

    Выкладываю полную документацию на устройство. Не успел запатентовать, поэтому надеюсь на вашу порядочность.

    Модуль Wifi ESP12F: G --> GND V --> 3.3V TX --> A3 RX --> A2
    Датчик температуры: S --> A5 G --> GND V --> 5V
    Перемычка 10 кОм: P13 --> Reset.
    photo_2026-04-19_08-57-23.jpg
    [​IMG]
    Код (Javascript):
    // V4.5.2 FLASH AUTOSTART
    var SSID = "Keenetic-9396";
    var PASSWORD = "xxxxxxxxxx";
    var HOST = "xxxxxxxxxx";
    var PORT = 5000;
    var PATH = "/webhook";
    var SEND_INTERVAL = 60000;
    var RETRY_INTERVAL = 15000;
    var DEVICE_ID = "iskra-01";
    var ESP_RESET_PIN = P13;
    var RESET_EVERY_SUCCESS_COUNT = 1;
    var MAX_QUEUE_SIZE = 20;
    var thermometer;
    var buf = "";
    var wifiReady = false;
    var sending = false;
    var initializing = false;
    var hardResetInProgress = false;
    var sendCount = 0;
    var atFailCount = 0;
    var nextSendTimer = null;
    var payloadQueue = [];
    var firstStart = true;
    var bootStarted = false;

    function log(msg) {
      print(msg);
    }

    function clearBuf() {
      buf = "";
    }

    function send(cmd) {
    //   log(">>> " + cmd);
      Serial2.write(cmd + "\r\n");
    }

    function sendRaw(data) {
      Serial2.write(data);
    }

    function hasAny(list) {
      for (var i = 0; i < list.length; i++) {
        if (buf.indexOf(list[i]) >= 0) return list[i];
      }
      return null;
    }

    function waitFor(okList, errList, timeout, ok, fail) {
      var t0 = getTime();
      var timer = setInterval(function() {
        var okFound = hasAny(okList);
        if (okFound) {
          clearInterval(timer);
          ok(okFound);
          return;
        }

        var errFound = hasAny(errList);
        if (errFound) {
          clearInterval(timer);
          fail(errFound);
          return;
        }

        if ((getTime() - t0) * 1000 > timeout) {
          clearInterval(timer);
          fail("TIMEOUT");
        }
      }, 200);
    }

    function pad2(n) {
      return (n < 10 ? "0" : "") + n;
    }

    function getDeviceTimeMsk() {
      var d = new Date();
      return (
        d.getFullYear() + "-" +
        pad2(d.getMonth() + 1) + "-" +
        pad2(d.getDate()) + " " +
        pad2(d.getHours()) + ":" +
        pad2(d.getMinutes()) + ":" +
        pad2(d.getSeconds())
      );
    }

    function getTemperature() {
      try {
        var t = thermometer.read("C");

        if (typeof t !== "number" || isNaN(t)) {
          return null;
        }

        return Math.round(t * 100) / 100;
      } catch (e) {
        // log("THERMOMETER READ ERROR");
        return null;
      }
    }

    function makePayload() {
      return {
        device_id: DEVICE_ID,
        send_count: sendCount + 1,
        device_time_msk: getDeviceTimeMsk(),
        message: "I did it",
        temperature: getTemperature()
      };
    }

    function buildRequest(payload) {
      var json = JSON.stringify(payload);

      return (
        "POST " + PATH + " HTTP/1.1\r\n" +
        "Host: " + HOST + ":" + PORT + "\r\n" +
        "Content-Type: application/json\r\n" +
        "Content-Length: " + json.length + "\r\n" +
        "Connection: close\r\n" +
        "\r\n" +
        json
      );
    }

    function cancelNextSend() {
      if (nextSendTimer) {
        clearTimeout(nextSendTimer);
        nextSendTimer = null;
      }
    }

    function scheduleNextSend(delay) {
      cancelNextSend();

      nextSendTimer = setTimeout(function() {
        nextSendTimer = null;
        sendWebhook();
      }, delay);
    }

    function finishSend(success) {
      if (success) {
        sendCount++;
        // log("SEND OK #" + sendCount);
      } else {
        // log("SEND FAILED");
      }

      sending = false;
    }

    function hardResetEsp() {
      if (hardResetInProgress) return;

      hardResetInProgress = true;
      wifiReady = false;
      sending = false;
      initializing = false;
      clearBuf();
      cancelNextSend();

    //   log("ESP HARD RESET");

      pinMode(ESP_RESET_PIN, "output");
      digitalWrite(ESP_RESET_PIN, 0);

      setTimeout(function() {
        pinMode(ESP_RESET_PIN, "input");
        // log("ESP RESET RELEASED");

        setTimeout(function() {
          clearBuf();
          atFailCount = 0;
          hardResetInProgress = false;
          initWifi();
        }, 5000);
      }, 500);
    }

    function scheduleReconnect() {
      wifiReady = false;
      sending = false;

      if (initializing || hardResetInProgress) return;

      cancelNextSend();
    //   log("REINIT IN " + (RETRY_INTERVAL / 1000) + " SEC");
      scheduleNextSend(RETRY_INTERVAL);
    }

    function maybeDoPeriodicReset() {
      if (sendCount > 0 && (sendCount % RESET_EVERY_SUCCESS_COUNT) === 0) {
        // log("PERIODIC ESP RESET");
        hardResetEsp();
        return true;
      }
      return false;
    }

    function enqueuePayload(payload) {
      payloadQueue.push(payload);

      if (payloadQueue.length > MAX_QUEUE_SIZE) {
        payloadQueue.shift();
        // log("QUEUE DROP OLDEST");
      }

    //   log("QUEUE SIZE " + payloadQueue.length);
    }

    function hasQueuedPayload() {
      return payloadQueue.length > 0;
    }

    function getCurrentPayloadForSend() {
      if (hasQueuedPayload()) {
        return payloadQueue[0];
      }

      var payload = makePayload();
      payloadQueue.push(payload);
    //   log("QUEUE SIZE " + payloadQueue.length);
      return payloadQueue[0];
    }

    function markFrontPayloadSent() {
      if (payloadQueue.length > 0) {
        payloadQueue.shift();
      }
    //   log("QUEUE SIZE " + payloadQueue.length);
    }

    function initWifi() {
      if (initializing || hardResetInProgress) return;

      initializing = true;
      wifiReady = false;
      clearBuf();

      send("AT");
      waitFor(["OK"], ["ERROR"], 3000, function() {
        atFailCount = 0;

        clearBuf();
        send("ATE0");
        waitFor(["OK"], ["ERROR"], 3000, function() {

          clearBuf();
          send("AT+CWMODE=1");
          waitFor(["OK", "no change"], ["ERROR"], 5000, function() {

            clearBuf();
            send('AT+CWJAP="' + SSID + '","' + PASSWORD + '"');

            waitFor(
              ["OK"],
              ["FAIL", "ERROR"],
              30000,
              function() {
                setTimeout(function() {
                  wifiReady = true;
                  initializing = false;
                //   log("WIFI READY");

                  if (firstStart) {
                    firstStart = false;
                    scheduleNextSend(1000);
                  } else if (hasQueuedPayload()) {
                    scheduleNextSend(1000);
                  }
                }, 1000);
              },
              function(reason) {
                initializing = false;
                // log("ERROR: WIFI INIT FAIL " + reason);
                scheduleReconnect();
              }
            );

          }, function(reason) {
            initializing = false;
            // log("ERROR: CWMODE FAIL " + reason);
            scheduleReconnect();
          });

        }, function(reason) {
          initializing = false;
        //   log("ERROR: ATE0 FAIL " + reason);
          scheduleReconnect();
        });

      }, function(reason) {
        initializing = false;
        atFailCount++;
        // log("ERROR: AT FAIL " + reason + " COUNT=" + atFailCount);

        if (atFailCount >= 3) {
          hardResetEsp();
        } else {
          scheduleReconnect();
        }
      });
    }

    function startTcp(req) {
      clearBuf();
      send('AT+CIPSTART="TCP","' + HOST + '",' + PORT);
      waitFor(
        ["CONNECT", "OK", "ALREADY CONNECTED"],
        ["ERROR", "CLOSED", "busy p..."],
        12000,
        function() {

          setTimeout(function() {
            clearBuf();
            send("AT+CIPSEND=" + req.length);
            waitFor(
              [">"],
              ["ERROR", "busy", "link is not valid"],
              6000,
              function() {

                clearBuf();
                sendRaw(req);
                waitFor(
                  ["SEND OK"],
                  ["ERROR", "SEND FAIL", "busy", "link is not valid"],
                  12000,
                  function() {
                    setTimeout(function() {
                      markFrontPayloadSent();
                      finishSend(true);
                      clearBuf();

                      if (!maybeDoPeriodicReset()) {
                        if (hasQueuedPayload()) {
                          scheduleNextSend(2000);
                        } else {
                          scheduleNextSend(SEND_INTERVAL);
                        }
                      }
                    }, 2000);
                  },
                  function(reason) {
                    // log("ERROR: SEND FAIL " + reason);
                    finishSend(false);
                    scheduleReconnect();
                  }
                );

              },
              function(reason) {
                // log("ERROR: NO SEND PROMPT " + reason);
                finishSend(false);
                scheduleReconnect();
              }
            );
          }, 1000);

        },
        function(reason) {
        //   log("ERROR: CIPSTART FAIL " + reason);
          finishSend(false);
          scheduleReconnect();
        }
      );
    }

    function sendWebhook() {
      if (hardResetInProgress) {
        // log("RESET IN PROGRESS");
        return;
      }

      if (initializing) {
        // log("INIT IN PROGRESS");
        return;
      }

      if (!wifiReady) {
        // log("WIFI NOT READY");
        initWifi();
        return;
      }

      if (sending) {
        // log("SEND SKIPPED");
        return;
      }

      sending = true;

      var payload = getCurrentPayloadForSend();
      var req = buildRequest(payload);

      startTcp(req);
    }

    function periodicTick() {
      if (!hasQueuedPayload()) {
        enqueuePayload(makePayload());
      } else {
        // log("QUEUE NOT EMPTY, SKIP NEW SAMPLE");
      }

      sendWebhook();
    }

    function startMainTimer() {
      scheduleNextSend(1000);

      setInterval(function() {
        periodicTick();
      }, SEND_INTERVAL);
    }

    function onInit() {
      if (bootStarted) return;
      bootStarted = true;

      buf = "";
      wifiReady = false;
      sending = false;
      initializing = false;
      hardResetInProgress = false;
      sendCount = 0;
      atFailCount = 0;
      nextSendTimer = null;
      payloadQueue = [];
      firstStart = true;

      thermometer = require("thermometer").connect(A4);

      Serial2.setup(115200, { rx: A3, tx: A2 });
      E.setTimeZone(3);

      pinMode(ESP_RESET_PIN, "input");

      Serial2.removeAllListeners("data");
      Serial2.on("data", function(d) {
        buf += d;

        if (buf.length > 4000) {
          buf = buf.slice(-2000);
        }
      });

      startMainTimer();
      initWifi();
    }
     
    Последнее редактирование: 19 апр 2026
  16. Ariadna-on-Line

    Ariadna-on-Line Гуру

    Аххренеть не встать. У вас в данный момент - Два компа + два роутера + Ардуина + Вай-фай модуль + два УСБ модема. И при этом ВСЁ в зоне досягаемости ВСЕГО. Мдя. Разбирайтесь сами. Здесь вам вряд ли помогут при таком положении дел. Чудес на свете не бывает.
     
  17. griefman

    griefman Нерд

    И что? Ещё в этой комнате СмартТВ, три телефона(Андроид и два Эпла), принтер, 3Д-принтер, блютуз-колонки и много чего еще.
     
  18. ZAZ-965

    ZAZ-965 Гуру

    @griefman, на Troyka Wi-Fi стоит свой стабилизатор 3,3В, я бы запитал этот модуль от 5В. На Iskra JS переключатель VIN3+5V и питать от внешнего источника 7,5В или 12В. На Iskra JS стоит стабилизатор MC7805BD на 1А - хватит и на STM32F405RG и на ESP8266 со своими стабилизаторами на 3.3V.
     
  19. Ariadna-on-Line

    Ariadna-on-Line Гуру

    "...Подключил устройство к компьютеру, отключил у него сеть..." - . У кого/у чего - отключили сеть ? У Ардуины или у компа ? Если у Ардуины - то вообще получаются чудеса - как без передатчика идет передача ? Если у компа - то бишь вы выдернули из розетки 220В роутер компа ? Значит второй роутер напрямую ловит вашу ардуину не выходя в интернет. Как говорят физики - правильно сформулированный вопрос - половина ответа. А так получается гадание на хрустальном шаре.
     
  20. griefman

    griefman Нерд

    Ваши многочисленные фантазии на тему "кто к кому подключен и кто без кого жить не может" меня просто поражают. Я уже писал, что плата вполне себе работает и передает информацию, будучи подключенной к компьютеру, у которого не загружена ОС и не имеющего, таким образом соединения, с внешним миром. Фактически, плата просто запитывается от БП компа, без подключения через него к сети. Или я не прав и плата сама как-то мимо ОС в корпусе системного блока находит лазейку во внешний мир? Плата же коннектится со стареньким роутером Keenetic-9396 c логином и паролем, записанными во флеш в скрипте, опубликованном выше.