Настраиваемое ядро для Arduino

Тема в разделе "Глядите, что я сделал", создана пользователем DIYMan, 20 дек 2017.

  1. DIYMan

    DIYMan Guest

    Ну так я ж для сэбэ, для того, чтобы избавиться от рутины, на РТОС не претендую, никому ничего не навязываю. Вот напишу еще асинхронный транспорт через ESP когда-нибудь, да конфигурационный софт - и будет у меня для меня удобный инструмент для старта любого, практически, проекта. В том числе - с юзеринтерфейсом, ибо всё, что я делаю - оно неблокирующее ;)
     
    IvanUA и ИгорьК нравится это.
  2. ИгорьК

    ИгорьК Гуру

    Знаете в чем проблема? В безумном количестве информации, которую приходится перерабатывать (а она, подлюка, норовит еще и из головы сбежать :) ). Здесь и спасают проверенные типовые решения (та же RTOS ). Наверно Вы сделаете что-то лучше и легче... но добавите в копилку "с этим надо разбираться" еще одну стопку байтов :)
    Это так, мысли...
     
    shpock и DIYMan нравится это.
  3. DIYMan

    DIYMan Guest

    Есть такое. Поэтому и пишу это дело, только когда вдохновение находит :) Коллега-электронщик, кстати, уже внедряет ядро в рабочий проект - уже есть поддержка LoRa и RS-485, помимо датчиков. Так что, можно сказать, уже самую капельку востребовано :)
     
    ИгорьК нравится это.
  4. DIYMan

    DIYMan Guest

    Начал делать конфигуратор ядра (первая версия, конечно, страшненькая :D):

    screen.png

    На скрине видно, что ужжо соединяется с портом, посылает команды, чего-то там получает в ответ - при этом контроллер непрерывно серет в порт всякой не относящейся к делу дребеденью. Старт дан, что называется ;) - далее буду потихоньку припиливать всякие настройки и прочую лабуду, чтобы на выходе был софт, позволяющий быро настроить периферию, всякие там MQTT и прочее, и чтоб осталось дело только за написанием логики конкретного проекта (на этот счёт тоже есть мысли, заюзать что-то типа IL, но тут пока сильно думаю).
     
  5. DIYMan

    DIYMan Guest

    Чуть причесал, добавил парсинг показаний с датчиков:

    screen.png

    Уже не так страшно, но всё равно - пока черновая версия ;)
     
  6. Vvlad1973

    Vvlad1973 Нуб

    Занятно... Если не секрет, сколько ядро памяти отъедает во флеш и в ОЗУ?
     
  7. DIYMan

    DIYMan Guest

    Это зависит от настроек условной компиляции. Сейчас, с включённой поддержкой датчиков всех типов, LoRa, RS-485, костяка работы с ESP - при компиляции под Mega2560 занимает 42К флеша и 1442 байта оперативки. Это ещё, конечно, не оптимизировано, но фарша там уже напихано много - ядро умеет обмениваться информацией с датчиков по RS-485, принимать пакеты с показаниями через LoRa и ещё кучу плюшек. Памяти пока хватает ;)
     
  8. DIYMan

    DIYMan Guest

    Кстати, крайняя версия конфигуратора - уже можно локально датчики добавлять:

    screen.png
     
  9. DIYMan

    DIYMan Guest

    Конфиг уже выгружается из конфигуратора в контроллер, добавил (но пока не тестировал) обмен данными по LoRa между слейвами и мастером, прикрутил просмотр данных с SD:

    screen.png

    Собственно, текущую версию уже можно назвать минимальной обвязкой для построения сети устройств. Следующим большим этапом будет - прикручивание работы с ESP через AT-команды, в дальнейшем, когда буду адаптировать прошивку на загрузку в саму ESP - будет работа с ESP изнутри ESP. Главный пойнт этого дела - MQTT.
     
  10. DIYMan

    DIYMan Guest

    Внедрил сигналы: флаги, настраиваемые на состояние хранилища - отсутствие информации с датчика, попадание информации в диапазон, сравнение "больше", "меньше" и т.п., работа по расписанию. Сигналы настраиваются через конфигуратор, далее - в логике конкретного проекта можно очень просто ими манипулировать, не задумываясь, какие конкретно условия взвели сигнал:
    Код (C++):
    if(Signals[10])
    {
      Serial.println(F("Signal #10 is raised!"));
      Signals[10] = 0; // reset signal
    }
    В конфигураторе для справочных целей есть карта сигналов. Выглядит это в первой версии вот так:

    screen.png screen2.png

    Всё, теперь, после правки возможных ошибок/недочётов при работе с сигналами - можно браться за внедрение поддержки ESP, наконец-то. Но уже сейчас на основе ядра можно построить проект с распределённой сетью устройств, и довольно гибко настраиваемых ;)
     
  11. DIYMan

    DIYMan Guest

    Прикрутил поддержку ESP - теперь ядро могёт в простенький веб-сервер, выдавая файлы с флешки, а также понимая все команды управления, типа http://ip/SET=PIN/13/ON:

    screen.png
    На основе этого уже можно вебморду корячить, если хочется. Осталось поддержку MQTT, и, считай - всё: потом отладка, тестирование, допиливание - и в оконцове я вообще не парюсь со стартом любого сложного проекта: всё будет "искаропки".
     
    ИгорьК нравится это.
  12. DIYMan

    DIYMan Guest

    Всё, MQTT работает:

    screen.png screen2.png

    На Андроиде в клиенте MQTT Dash - тоже всё показывается, офигенски! При этом на втором скриншоте видно, что одновременно работает конфигуратор, запрос с браузера, и пуляются данные в MQTT-брокер.

    Теперь дело за транспортом через SIM800 - и будет полный фарш, т.к. класс клиента MQTT в прошивке умеет в любой транспорт пихать данные.

    При всём при этом - полный асинхрон всего, т.е. никаких блокирующих операций: всё на событиях, на честном С :D
     
    Vvlad1973 и ИгорьК нравится это.
  13. DIYMan

    DIYMan Guest

    Всё, на первый взгляд вроде SIM800 работает в ядре:

    screen.png

    Можно настраивать POWERKEY, управление пересбросом при зависании и пр. ништяки. Есть поддержка GPRS, правда, не тестировал ещё MQTT через SIM800, т.к. нет аккаунтов пока в облачных MQTT-сервисах (ну да это дело поправимое, потихоньку оттестируем). Для SIM800 можно забить несколько номеров телефонов, которые будут считаться хозяйскими. Реализована минимальная обвязка, необходимая для работы из логики конкретного проекта, вот выдержка из скетча:

    Код (C++):
    // Событие "Поступил входящий звонок". В первом параметре - номер телефона, второй параметр - сообщает, известный ли это номер телефона,
    // третий - если установлен, то трубка будет положена сразу же.
    //--------------------------------------------------------------------------------------------------------------------------------------
    void ON_INCOMING_CALL(const String& phoneNumber, bool isKnownNumber, bool& shouldHangUp)
    {
      Serial.print(F("Incoming call from: "));
      Serial.print(phoneNumber);
      Serial.print(F("; known number? "));
      if(isKnownNumber)
        Serial.println(F("KNOWN"));
      else
        Serial.println(F("UNKNOWN"));

      // кладём трубку
      shouldHangUp = true;

      // отправляем СМС в ответ
      #ifdef CORE_SIM800_TRANSPORT_ENABLED
        SIM800.sendSMS(phoneNumber, F("Не звони мне больше, редиска :)"), true);
      #endif
    }
    //--------------------------------------------------------------------------------------------------------------------------------------
    // Событие "Пришло СМС". В первом параметре - номер телефона, с которого пришло СМС, во втором - декодированное сообщение,
    // в третьем - флаг, что сообщение получено с известного номера
    //--------------------------------------------------------------------------------------------------------------------------------------
    void ON_SMS_RECEIVED(const String& phoneNumber,const String& message, bool isKnownNumber)
    {
        Serial.print(F("INCOMING SMS FROM: "));
        Serial.println(phoneNumber);
       
        Serial.print(F("INCOMING SMS TEXT: "));
        Serial.println(message);

        // отправляем СМС назад
        #ifdef CORE_SIM800_TRANSPORT_ENABLED
          static int smsCounter = 0;
          smsCounter++;
          String smsText = "Ответочка номер #";
          smsText += smsCounter;
          SIM800.sendSMS(phoneNumber, smsText, true); // последний параметр - flash или обычное смс
        #endif
    }
    //--------------------------------------------------------------------------------------------------------------------------------------
     
    Как видите - всё просто - есть события "поступило СМС" и "поступил входящий звонок". При этом есть информация - это с известного номера или нет. В логике конкретного проекта можно уже делать что-то конкретное с этой инфой ;)

    Короче, получается очень удобно, особенно - когда отлажу по самое не балуй. Всё, нужна передышка на пару дней, считаю, заслужил :)
     
  14. DIYMan

    DIYMan Guest

    Обновил ядро - введена поддержка публикации на ThingSpeak - как данных с хранилища, так и любых, нужных пользователю:

    screen.png screen2.png

    Пользовательские данные пушатся просто:

    Код (C++):
    // просим отправить на ThingSpeak наше значение в одно из полей канала
      #ifdef CORE_THINGSPEAK_TRANSPORT_ENABLED
        static unsigned long thingSpeakMillis = 0;
        if(millis() - thingSpeakMillis > 5000)
        {
          static int thingspeakData = 0;
          thingspeakData = random(50,500);

          // просим опубликовать наше рандомное число в поле номер 3. Допустимые диапазоны полей - 1-8.
          // при очередной публикации в ThingSpeak это рандомное число там появится.
          ThingSpeak.publish(3,String(thingspeakData));

          // ну и попросим опубликовать данные о свободной памяти контроллера в поле номер 4
          ThingSpeak.publish(4,String(Core.getFreeMemory()));
         
          thingSpeakMillis = millis();
        }
      #endif // CORE_THINGSPEAK_TRANSPORT_ENABLED
     
    ИгорьК нравится это.
  15. alex_rnd61

    alex_rnd61 Нерд

    А можно в конфигураторе сделать изменение скорости порта? И его закрытие тоже бы не помешало. В настройках RS485 выбор пина по номеру Arduino тоже не удобно. И сколько времени конфигуратор будет долбить модем, уже больше пяти минут его долбит? Таймаут есть?
     
  16. DIYMan

    DIYMan Guest

    1. Пока нет, чуть позже приделаю;
    2. Зачем закрытие? Оно не нужно, от слова "совсем";
    3. Мне удобно именно по номеру пина Ардуино;
    4. Не понял - кто кого и куда долбит. Какой модем? Вы о чём? Если о SIM800 - то надо настраивать, есть куча настроек, у меня работает с одними (юзается POWERKEY), у вас - будет с другими, например. Плюс не забывайте, что скорость UART для работы с устройствами должна быть такая, на которую настроено устройство.

    Никаких таймаутов при работе с устройствами нет - есть конечный автомат, который будет пытаться настроить устройство до победного, перекуривая в промежутках. Пойнт - лично мне надо систему, которая сама переконнекчивается к тому же роутеру, например. А просто вываливаться по таймауту - это не ко мне ;)
     
  17. alex_rnd61

    alex_rnd61 Нерд

    Скачал последнюю версию, сейчас с SIM800 нормально.
     
  18. DIYMan

    DIYMan Guest

    Чуть позже добавлю настройки в конфигуратор ;)
     
  19. alex_rnd61

    alex_rnd61 Нерд

    Как работать с 485 интерфейсом, если, например, датчики отдельно, на другом МК.
     
  20. DIYMan

    DIYMan Guest

    Обновил софт, добавил возможность выбора скорости соединения, плюс кнопку "Разорвать соединение".
    Сразу скажу, что пока RS-485 я не тестировал, но работать должно (не обязано, конечно, но должно). Ядро ещё только в процессе разработки, многое ещё тестировать надо - надеюсь, вы понимаете, что ждать всего-всего от проекта, которому без году неделя - не стоит ;) При работе по RS-485 сейчас реализовано только получение данных мастером со слейвов - мастер последовательно опрашивает 50 адресов (это максимальное кол-во слейвов на шине), и собирает информацию с их хранилищ. Единственное ограничение - названия датчиков в пределах одного кластера должны быть уникальны, т.к. мастер сливает всю информацию, полученную от слейвов - в своё хранилище.

    Если не надо этого добра, а надо какой-то свой протокол - в настройках прошивки можно указать, что не надо использовать логику ядра - тогда будет просто объект RS485, у которого есть методы
    Код (C++):
        // возвращает UART, используемый для RS-485
        HardwareSerial* getSerial() {return workStream; }

        void sendData(uint8_t* data, uint8_t dataSize); // отправляет данные в шину: переключается на передачу, посылает данные, после отсыла - переключается на приём
        void switchToReceive(); // переключается на приём
        void switchToSend(); // переключается на передачу
        void waitTransmitComplete(); //ждёт окончания передачи
    И можно этот объект юзать для общения по RS-485 по самописному протоколу, если надо.

    Работать с RS-485 с включенной логикой ядра просто: на всех МК залито ядро. На одном МК - ядро, сконфигурированное в режиме RS-485 мастер, на других МК - ядро, сконфигурированное в режиме RS-485 слейв. Всё - после этого данные хранилищ слейвов должны появиться на мастере.

    Если вы хотите другой МК, без установленного на него ядра - то это не совсем тривиально - надо самому писать разбор пакетов и отсыл информации. Фишка ядра в том, что оно всю эту работу сделает за вас ;)

    З.Ы. Документации пока никакой нету, звиняйте - всё в исходниках только. Если что - спрашивайте. И ещё раз подчеркну - это ещё сыровато местами, надо быть готовым ко всякому ;)