1 2 3 4 5 6 7 8 9 10 10/10 10,00оценок: 9

Arduino Mega. Контроллер теплицы. Хроники - 3.0

Тема в разделе "Умный дом", создана пользователем Анкор Плюс, 27.04.17.

Статус темы:
Закрыта.
  1. Old-Admiral
    Регистрация:
    30.03.16
    Сообщения:
    191
    Благодарности:
    153

    Old-Admiral

    Живу здесь

    Old-Admiral

    Живу здесь

    Регистрация:
    30.03.16
    Сообщения:
    191
    Благодарности:
    153
    Ха-ха, я тя пон :)], значт, сам я не догнал. Упустил глобальные изменения из виду.
    Счас прошивка скомпилировалась, всё норм.
    Чтоб без тебя делал!?!? :hndshk:
    Гран мерси, Дим! :hello:
     
  2. promavto
    Регистрация:
    27.02.16
    Сообщения:
    1.960
    Благодарности:
    1.958

    promavto

    Разработка контроллеров

    promavto

    Разработка контроллеров

    Регистрация:
    27.02.16
    Сообщения:
    1.960
    Благодарности:
    1.958
    Адрес:
    г. Москва, Зеленоград.
    Дима, вижу в ArduinoCore память уже определяется автоматически. Но может не стоит задирать до 512 по умолчанию, а скромненько указать 32 :)].
     
  3. DIYMan
    Регистрация:
    19.05.13
    Сообщения:
    8.309
    Благодарности:
    6.889

    DIYMan

    Любопытный рукосуй :)

    DIYMan

    Любопытный рукосуй :)

    Регистрация:
    19.05.13
    Сообщения:
    8.309
    Благодарности:
    6.889
    Адрес:
    80 км от Краснодара
    Ок, так и сделаю ;)
     
  4. DIYMan
    Регистрация:
    19.05.13
    Сообщения:
    8.309
    Благодарности:
    6.889

    DIYMan

    Любопытный рукосуй :)

    DIYMan

    Любопытный рукосуй :)

    Регистрация:
    19.05.13
    Сообщения:
    8.309
    Благодарности:
    6.889
    Адрес:
    80 км от Краснодара
    Оживим молчание, пока новостей по гироскопам нету ;) Добавил в ArduinoCore первый транспорт: RS-485. Он берёт на себя всю рутинную работу по приёму и разборке пакетов на шине RS-485. Алгоритм простой: указываете в конфиге описание пакета, и по приходу пакета этот транспорт вызывает событие, что, мол - пришёл такой-то пакет, делай с ним, друже, что хочешь. Такой подход позволит работать как в режиме slave, так и в режиме master, т. к. в логике доступен глобальный объект RS485, который имеет метод для записи в шину. Конфиг для RS-485 выглядит примерно так:
    Код:
          RS485SettingsRecord, // настройки RS-485
          6, // скорость работы с RS-485 (1 - 9600, 2 - 19200, 4 - 38400, 6 - 57600, 12 - 115200)    
          1, // номер Serial, который используется для работы с RS-485 (1 - Serial1, 2 - Serial2, 3 - Serial3)
          5, // пин управления приёмом-передачей MAX-485
        //---------------------------------------
          RS485IncomingPacketRecord, // данные по входящему пакету по RS-485
          3, // длина заголовка
          '1', '2', '3', // байты заголовка пакета
          5, // длина данных пакета (БЕЗ ЗАГОЛОВКА)
          123, // внутренний идентификатор пакета
        //---------------------------------------
          RS485IncomingPacketRecord, // данные по входящему пакету по RS-485
          2, // длина заголовка
          '9', '9', // байты заголовка пакета
          3, // длина данных пакета (БЕЗ ЗАГОЛОВКА)
          44, // внутренний идентификатор пакета
        //---------------------------------------
    
    Обработчик входящего пакета может быть вот таким:
    Код:
    void myRS485ReceiveHandler(byte packetID, byte receivedDataLen, byte* receivedData)
    {
      // в receivedData - все данные вместе с заголовком, длиной receivedDataLen
      // в packetID - внутренний идентификатор пакета, описанный в конфиге
    
      // тут чего-то делаем с пакетом, если надо послать назад какие-либо данные - пишем
    
      const char* dataToSend = "Hello!";
      byte dataToSendLen = strlen(dataToSend);
      RS485.sendData((byte*)dataToSend, dataToSendLen);
    
      // данные отправляются в виде потока байт, после отправки менеджер RS-485 сразу переключается на приём информации
    }
    
    Всё, остальное ядро сделает за вас: будет искать в потоке входящих байт заголовки известных пакетов, и принимать данные этих пакетов. Алгоритм синхронизации пакетов в потоке реализован: неважно, когда мы включились в шину - заголовки пакетов ищутся по мере прихода данных в шину, и начало фрейма данных синхронизируется именно по любому из заголовков пакетов, за которыми нам надо следить на шине.

    По итогу - руки ещё больше развязаны от рутины: можно работать непосредственно на уровне пакетов, не парясь, как там оно внутри устроено. Т. е. уже сейчас можно гонять данные по RS-485, когда душе угодно.

    Ещё нововведение - датчики с определяемыми пользователем данными, в конфиге выглядят вот так:
    Код:
          SensorRecord, // данные о датчике
          'U', 'D', '\0', // даём датчику имя "UD"
          UserDataSensor, // пользовательские данные любого вида
          1, // длина данных
          2, // длина буфера, хранимого датчиком - 2 байта
        //---------------------------------------
    
    После разбора конфига получить датчик по имени можно так:
    Код:
    CoreUserDataSensor* mySensor = (CoreUserDataSensor*) Core.Sensors()->get(F("UD"));
    И в любой интересующий момент обновлять в нём данные, прося ядро немедленно поместить их в общее хранилище:
    Код:
      // каждую секунду обновляем показания в нашем тестовом пользовательском датчике
      if(mySensor) // если такой датчик есть в конфиге
      {
        static unsigned long userDataSensorMillis = 0;
        static byte bUserData[] = {0,0xFF};
      
        if(curMillis - userDataSensorMillis > 1000)
        {
          userDataSensorMillis = curMillis;
        
          // просто меняем байтики
          bUserData[0]++;
          bUserData[1]--;
    
          // устанавливаем данные в датчик
          mySensor->setData(bUserData,sizeof(bUserData));
        
          // говорим ядру, чтобы НЕМЕДЛЕННО поместило данные с датчика в хранилище
          Core.pushToStorage(mySensor);
        }
      } // if(mySensor)
    Всё - теперь неважно, что там и с какой периодичностью делает ядро: мы можем из логики (например, в прерывании) немедленно обновить в хранилище данные для пользовательского датчика. Что тоже развязывает руки от рутины, т. к. сейчас логику можно писать, даже не имея никакого конфига, а в будущем, когда будет софт для настройки - при помощи софта закачать настроечный конфиг в плату - и вся логика сразу всё подцепит ;)

    Чую, развернём мы на этом деле умный дом ;), как только будет поддержка транспорта через ESP по протоколу MQTT.

    Есть ещё мысли по формированию простейших правил поведения для ядра, типа как реализованы правила в контроллере теплицы, только проще и наглядней. Пока обдумываю, как это сделать - всё-таки нет задачи сделать аналог FLProg, как ни крути - хочется удобного юзабельного варианта, где всё понятно и наглядно. Вскрытие покажет, в общем.

    Не скучайте тут без меня ;), а то я продолжу сыпать всякими непонятностями :)]:aga: И просьба: кому интересны здесь новости про ArduinoCore - поставьте плюсик к сообщению, чтобы я понял, надо ли всё-таки тут такие перебивки информационные вставлять ;)
     
  5. DIYMan
    Регистрация:
    19.05.13
    Сообщения:
    8.309
    Благодарности:
    6.889

    DIYMan

    Любопытный рукосуй :)

    DIYMan

    Любопытный рукосуй :)

    Регистрация:
    19.05.13
    Сообщения:
    8.309
    Благодарности:
    6.889
    Адрес:
    80 км от Краснодара
    Написал в ArduinoCore поддержку выдачи конфига во внешний мир, теперь на команду GET=CONFIG в монитор порта падает примерно такое:
    Код:
    OK=CONFIG|50ED9F02000402002302000402005C02000301000200020201050252544300050100020006010002445331000101060244533200010106020007010D0200080137020008013802355600080139025544000901020500000001466C79004874526A37554A51000C0100001E020201070601050803313233057B08023939032C032C0400060550
    
    Весь конфиг выдаётся наружу, как есть. Пока не решил, годный это подход или нет, т. к. конфиг будет немаленьким. С другой стороны - это дело софта, разбирать такой конфиг автоматически и показывать его юзеру в удобочитаемом виде.

    Прошёлся ручками, проверил каждый байт - ттт, совпадает, значит, итерируется правильно (ядро заранее не знает о размере конфига, в этом вся фишка - оно читает его от записи к записи).

    Оставлю вылежаться это дело на денёк-другой, надо продумать всякие нюансы, но уже сейчас можно сказать, что получающееся - нравится, по настройкам будет масса всего, и главное - без перезакачки прошивки. Более того, что самое интересное - в софте можно сделать отдельную кнопу "выгрузить конфиг в формате исходного кода", которая что? Правильно - позволит сделать жёстко вшитую в код настройку какого-либо специфического проекта, ну или - просто конфиг по умолчанию, если нет сохранённого в EEPROM (для этого предусмотрены все функции - если не загрузили с EEPROM - всегда можно загрузить конфиг по умолчанию из флеша).

    Короче, получается, ттт, годно. Конфигурационный софт бы вот кто-то за меня ещё написал :)]:aga:
     
  6. promavto
    Регистрация:
    27.02.16
    Сообщения:
    1.960
    Благодарности:
    1.958

    promavto

    Разработка контроллеров

    promavto

    Разработка контроллеров

    Регистрация:
    27.02.16
    Сообщения:
    1.960
    Благодарности:
    1.958
    Адрес:
    г. Москва, Зеленоград.
    Привет сообществу! Дима, планируется работа Arduino Core c файловой системой или передачи массива данных в ближайшее время? Лепить самому или стоит немного подождать, не срочно. :)] Планируешь ли транспорт по WiFi, LoRa, nRF24l01?
     
  7. DIYMan
    Регистрация:
    19.05.13
    Сообщения:
    8.309
    Благодарности:
    6.889

    DIYMan

    Любопытный рукосуй :)

    DIYMan

    Любопытный рукосуй :)

    Регистрация:
    19.05.13
    Сообщения:
    8.309
    Благодарности:
    6.889
    Адрес:
    80 км от Краснодара
    1. По массивам данных - уже сейчас есть RS-485, куда можно записать в любое время что угодно;
    2. По файловой системе - пока не знаю, не вижу тут того, что можно было бы сделать универсальным;
    3. Передача содержимого файлов через транспорт - будет транспорт, там будут клиенты, которые могут писать данные через любой транспорт. В логике надо будет только блочно передавать файл, и всё (будут тонкости в логике, т. к. передача асинхронная, но я примеры напишу);
    4. Первый транспорт - это ESP будет, остальные - LoRa и пр. - по мере востребованности.

    Всё это дело небыстрое, работы много, так что в ближайшее время ждать любого транспорта, отличного от уже реализованного RS-485 - не стоит ;)
     
  8. promavto
    Регистрация:
    27.02.16
    Сообщения:
    1.960
    Благодарности:
    1.958

    promavto

    Разработка контроллеров

    promavto

    Разработка контроллеров

    Регистрация:
    27.02.16
    Сообщения:
    1.960
    Благодарности:
    1.958
    Адрес:
    г. Москва, Зеленоград.
    Ок! Может имеет смысл написать небольшой текстовый файл с примерами команд типа GET SET. Я перерыл всю программу - ищу запись времени. Может народ быстрее подтянется к теме когда понятно будет как писать или получать данные и в каком виде. А мне нужно выводить время на дисплей. С этим проблемы не вижу. А вот устанавливать время с меню дисплея пока не нашел куда и как писать.
    Ты сообщал, что добавил эту возможность. Пока не нахожу. Ответ не срочно. переделывать буду в понедельник
     
  9. DIYMan
    Регистрация:
    19.05.13
    Сообщения:
    8.309
    Благодарности:
    6.889

    DIYMan

    Любопытный рукосуй :)

    DIYMan

    Любопытный рукосуй :)

    Регистрация:
    19.05.13
    Сообщения:
    8.309
    Благодарности:
    6.889
    Адрес:
    80 км от Краснодара
    Да там пока команд общения с внешним миром - мизер, чуть позже напишу примеры. Что касается времени: то из монитора порта его можно установить, передав строку вида
    , на примере:
    И время автоматом установится на все DS3231, которые прописаны в конфиге. Ручками из кода этого не сделать, да и незачем. Просто в мониторе порта ввести - и всё. Если нужно именно с меню дисплея - ок, я напишу поддержку такой функции в ядре.
     
  10. promavto
    Регистрация:
    27.02.16
    Сообщения:
    1.960
    Благодарности:
    1.958

    promavto

    Разработка контроллеров

    promavto

    Разработка контроллеров

    Регистрация:
    27.02.16
    Сообщения:
    1.960
    Благодарности:
    1.958
    Адрес:
    г. Москва, Зеленоград.
    У меня не строковые данные, а типа как в библиотеке:
    DS3231_clock.setDate (t_temp_date, t_temp_mon, t_temp_year);
    DS3231_clock.setTime (t_temp_hour, t_temp_min, t_temp_sec);
    Спасибо.
     
  11. DIYMan
    Регистрация:
    19.05.13
    Сообщения:
    8.309
    Благодарности:
    6.889

    DIYMan

    Любопытный рукосуй :)

    DIYMan

    Любопытный рукосуй :)

    Регистрация:
    19.05.13
    Сообщения:
    8.309
    Благодарности:
    6.889
    Адрес:
    80 км от Краснодара
    Добавил, см. функцию
    Т. е. в любом месте вызываем:
    и всё.
     
  12. promavto
    Регистрация:
    27.02.16
    Сообщения:
    1.960
    Благодарности:
    1.958

    promavto

    Разработка контроллеров

    promavto

    Разработка контроллеров

    Регистрация:
    27.02.16
    Сообщения:
    1.960
    Благодарности:
    1.958
    Адрес:
    г. Москва, Зеленоград.
    Спасибо! В понедельник буду внедрять.
    А Core. getCurrentDateTime (day, month, year, hour, minute, second); или что то похожее ты уже, кажется сделал.
     
  13. DIYMan
    Регистрация:
    19.05.13
    Сообщения:
    8.309
    Благодарности:
    6.889

    DIYMan

    Любопытный рукосуй :)

    DIYMan

    Любопытный рукосуй :)

    Регистрация:
    19.05.13
    Сообщения:
    8.309
    Благодарности:
    6.889
    Адрес:
    80 км от Краснодара
    Получение показаний с DS3231 есть в примерах, там всё точно так же, как и с другими датчиками в хранилище, писать специальную функцию - не надо. Вот, из примера в скетче (датчику DS3231 дано имя "RTC"):
    Код:
     ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        // ПРИМЕР ПОЛУЧЕНИЯ ДАННЫХ С DS3231 в виде структуры (датчику в конфиге прописано имя "RTC")
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
         DateTimeData currentDateTime = CoreDataStore.get(F("RTC"));
         Serial.print(F("DATETIME: "));
         Serial.print(currentDateTime.day);
         Serial.print('.');
         Serial.print(currentDateTime.month);
         Serial.print('.');
         Serial.print(currentDateTime.year);
         Serial.print(' ');
    
         Serial.print(currentDateTime.hour);
         Serial.print(':');   
         Serial.print(currentDateTime.minute);
         Serial.print(':');   
         Serial.print(currentDateTime.second);
    Можно получать и не по имени, а по типу показаний:
    Код:
    CoreDataList allDateTime = CoreDataStore.getByType(DateTime);
    DateTimeData currentDateTime = allDateTime[0]; // текущие дата/время с первого DS3231 в конфиге.
    
     
    Последнее редактирование: 13.01.18
  14. promavto
    Регистрация:
    27.02.16
    Сообщения:
    1.960
    Благодарности:
    1.958

    promavto

    Разработка контроллеров

    promavto

    Разработка контроллеров

    Регистрация:
    27.02.16
    Сообщения:
    1.960
    Благодарности:
    1.958
    Адрес:
    г. Москва, Зеленоград.
    Не вижу больше проблем для внедрения ядра, за исключением - ты будешь добавлять, а мне придется каким то образом добавлять изменения. Буду вести перечень сделанных мною изменений.
     
  15. DIYMan
    Регистрация:
    19.05.13
    Сообщения:
    8.309
    Благодарности:
    6.889

    DIYMan

    Любопытный рукосуй :)

    DIYMan

    Любопытный рукосуй :)

    Регистрация:
    19.05.13
    Сообщения:
    8.309
    Благодарности:
    6.889
    Адрес:
    80 км от Краснодара
    Начал припиливать LoRa, пока только программно, завтра, даст бог, попробую подключить железки для тестирования. В ядре пока выглядит вот так:

    Код:
    // пример работы с LoRa: определяем функцию с именем ON_LORA_RECEIVE (это имя обязательно!!!),
    // внутри неё работаем с глобальным объектом LoRa. В packetSize - длина пришедших данных.
    // Если настройка CORE_LORA_TRANSPORT_ENABLED закомментирована в CoreConfig.h - то глобальный
    // объект LoRa будет недоступен !!!
    //--------------------------------------------------------------------------------------------------------------------------------------
    void ON_LORA_RECEIVE(int packetSize)
    {
    
      Serial.println(F("Packet received from LoRa: "));
    
    
      while (LoRa.available())
      {
        // в коллбэке читать из LoRa только побайтово!!
        Serial.print((char)LoRa.read());    
      }
    
      // посылаем данные назад
      static int counter = 0;
      counter++;
      String outgoing = "Ping back #";
      outgoing += counter;
    
      LoRa.beginPacket();                   // начинаем пакет
      LoRa.print(outgoing);                 // пишем нашу строку
      LoRa.endPacket();                     // заканчиваем пакет
    
      LoRa.receive();  // переключаемся на приём
    
    }
    //--------------------------------------------------------------------------------------------------------------------------------------
    Короче, всё просто - включена поддержка LoRa - можно определить функцию ON_LORA_RECEIVE, и она будет дёргаться по приходу любого пакета с LoRa. Доступен глобальный объект LoRa, который можно попросить выплюнуть данные в эфир в любое время, когда это нужно логике конкретного проекта.

    Настройки LoRa - в конфиге, они - вот они какие, красавцы:
    Код:
          LoRaSettingsRecord, // данные по настройкам LoRa
          3, // частота работы с LoRa, Hz (1 - 433E6, 2 - 866E6, 3 - 915E6)
          10, // пин SS для LoRa
          0xFF, // пин RESET для LoRa (0xFF - не назначен)
          3, // пин DIO0 для LoRa (пин с прерываниями!!!)
          17, // мощность передатчика, dB (2-17)
          8, // ширина полосы пропускания сигнала, Hz (1 - 7.8E3, 2 - 10.4E3, 3 - 15.6E3, 4 - 20.8E3, 5 - 31.25E3, 6 - 41.7E3, 7 - 62.5E3, 8 - 125E3, 9 - 250E3)
          0, // использовать или нет CRC (0 - не использовать, 1 - использовать)
    
    Собственно, всё довольно просто, и вроде даже скомпилировалось :) Осталось проверить на железках, и если всё гуд - в ArduinoCore появится поддержка LoRa из коробки, что называется.

    Если всё получится (а я верю), то будет возможность пихать данные в эфир, когда надо - в логике знай себе формируй пакеты, и пихай. Ну и - слушай эфир, конечно же.

    Конечно, сейчас тестовый скетч выглядит несколько сумбурно, но на самом деле, если убрать всю тестовую информацию - он станет буквально пустым, строчек на 10. Т. е. готовым к написанию логики, и уже предоставляющим события о приходе данных из внешнего мира. Кмк, удобный инструмент. Хотя - фломастеры всегда разные на вкус :)
     
    Последнее редактирование: 14.01.18
Статус темы:
Закрыта.