Digital controller for incubator — release version

Наконец-таки я закончил работу над этим девайсом.
Проверен хард и софт. Теперь могу выложить это open-hardware проект в блоге.

SAM_4961

1. Что оно умеет
Это устройство предназначено для управления инкубатором, состоит из цифрового термостата с плавным регулированием мощности и таймера для поворота яиц. Собрано на 32-х битном микроконтроллере STM32 (STM32F030F4P6) с ядром Cortex M0.

Список функций:
– цифровой термометр на DS18B20 с возможностью ввода калибровочных коэффициентов,
– регулятор мощности с фазовым управлением симистором,
– ПИ-регулятор с возможностью регулировки коэффициентов и экспериментальной функцией автоматической настройки,
– звуковая сигнализация при неисправности датчика и нагревателя,
– сохранение параметров в энергонезависимой памяти

2. Схемы

(кликабельно)

Incub_control

Incub_power

Силовая плата фактически однослойная. Плата управления — один слой разводка, второй — земля.

Отдельно можно скачать схемы и печатные платы по слоям в pdf.

3. Проекты
Исходники [Keil MDK-ARM] и схема [Eagle] в Github

4. Как программировать
– Скачать прошивку в hex
– Скачать и установить STM32 Flash loader demonstrator.
– Собрать следующую схему (просто два инвертора между COM-портом и микроконтроллером)

RS-232
– Поставить перемычку JP1 “Bootloader”
– Загрузить прошивку с помощью Floash loader прошивку ( как пользоваться написано тут )

5. Как пользоваться.
Пока есть такое видео.

Объяснения пунктам в меню.

Группа Basic — базовые настройки
– Temp.ref — установка температуры;
– Rot.int — интервал, через который включается поворот (минуты);
– Rot.dur — время, на которое включается поворот (логическая 1 на выводе PA10), в секундах;

Группа Advancd — технические настройки
– T. Ofst и T. Gain — калибровочные коэффициенты термодатчика ([показания] = “T. Gain”*[измеренное датчиком] + “T. Ofst”);
– PID K_P и PID K_I — коэффициенты ПИ-регулятора;
– PID Auto — активация/завершение автоматической настройки ПИ-регулятора

Кнопки (начиная с левой)
1 — вызов меню, возврат из меню;
2 — переход к изменению параметра в меню, выбор разряда;
3 — инкремент разряда, изменение параметра.

Как сделать автоматическую настройку. Надо включить инкубатор, установить очень низкую температуру (например, 10 градусов) — так, чтобы нагреватель был выключен. Как только температура установится, то войти в меню PID Auto, нажатиями кнопок 2 и 3 включить автоматическую настройку. При этом будет отображаться температура и нагреватель включится на полную мощность. Как только температура установится (надо дождаться), нажать кнопку 3 — будет выведено сообщение “ok” или “failed”, в зависимости от результата автонастройки. Обязательно надо зайти в PID K_P и PID K_I — посмотреть что там записалось.

Еще есть видо автоматической настройки и работы регулятора с коэффициентами после автонастройки.

18 thoughts on “Digital controller for incubator — release version

  1. Hello.

    I’m really interested in this project since I’ve been looking for a PID temperature module controlling a oven with a LCD+menu to control the set temperature. I dont read russian so I can’t really follow whats included, what teperature (and humidity?) sensor used and if a relay (ssr?) to contoll the heating is included. I would like to use the DHT22. I also can’t make the PCB myself. So I wonder if you sell this board and a list of the parts used?
    I’m most impressed.
    Best regards
    Marcus Nordgren / Sweden

    • Hi, Marcus! Sorry, for late reply.
      Humidity sensor is not implemented yet. 😦 However it will be done in meantime.
      Temperature control based on DS18b20 sensor and triac BT138.
      For PCB you can order by yourself at Itead Studio the empty board and then assembly it (or ask someone). I have some boards already assembled, but not ready yet to sell it worldwide…

      • Thank you for your reply. I will continue to follow your progress, then we’ll see when it’s ready to go ‘wordwide’ 🙂
        The best of luck.
        Marcus

  2. Добрый день.
    А продолжение по данному проекту планируете? = задумка классная, но от потребностей птицевода реализовано примерно 30%.
    может продолжим данную тематику, сделав современный контроллер для домашней инкубации?

      • Это радует.
        В таком случае предлагаю перейти в электронку, ибо объем переписки будет неудобным для формата комментариев.
        Моя электронка nav68@rambler.ru,
        Александр.

  3. Смотрел ваши исходники на 072…
    Уважаемый, вы вообще в курсе что сей чип имеет аппаратную поддержку modbus, что RTU что ASCII? Имеет аппаратный модуль CRC. Про i2C и uart вообще молчу , HAL просто портит их.

    • Здравствуйте.
      На всякий случай позволю уточнить, речь идет про новый проект — который с Bluetooth https://github.com/akpc806a/Bluetooth_incubator
      Про поддержку Modbus никогда не слышал и ничего не нашел тем болле про ASCII (ни одного упоминания в PM0215 Programming manual). Можете ткнуть носом? Возможно вы имеете в виду, что там есть аппаратная поддержка сигнала DE для RS-485. Но я использую Modbus поверх Bluetooth, там полный дуплекс.
      HAL — удобная вещь, особенно визуальный конфигуратор STM32CubeMX. КОгда много проектов и много железа, покликал там — и уже готовый прототип кода, который можно облагораживать))

      • Ок. Завтра ткну.
        А пока прочитайте , но не Programming manual а Reference manual.

    • Интересно. Почитал. Спасибо большое.
      Я полагал, что это поддержка протокола (ну хотя бы распознавание адреса), а только про синхронизацию. Но все равно полезно — надо добавить.
      Я пытался сделать свой код Modbus простым и независимым от платформы. К тому же он проверен во многих проектах, не только в STM32, но PIC32 и в Altera Nios.

    • А что про I2C и UART вам еще не понравилось? то что там блокирующие вызовы процедур?
      Вы должно быть действительно разбираетесь в STM32, интересно ваше мнение.

      ps: Исходники еще пока конечно не готовы, их стоит сильно подчистить. и распутать некоторую лапшу. Поэтому я и не писал про этот проект в блоге, потому что он еще в разработке. Нет некоторых фич.

      • Ну, здесь как обычно, либо универсально- в итоге получаем ту же аурдунью и тот же софтовый ногодрыг либо используем аппаратные плюшки .
        Как вы наверное уже прочитали, аппаратная поддержка модбас состоит в прерывания по таймауту(rtu) либо по определенному символу(ASCIi).
        В купе с DMA, позволяет принимать пакеты полностью аппаратно.
        В прерывании смотрим счетчик транзакций DMA == знаем длину пакета. Далее , модуль CRC. В итоге от исходников freemodbus, что вы используете , останется только верхний уровень -парсинг пакетов и т.д. Но придется потрудиться.
        USART , инициализация его и DMA займет десяток строк вместе с инитом пинов. Никаких каловский колбэков и прочей ереси, все будет аппаратно. Инит тактирования так же не имеет что либо сложного, чтобы использовать визарды и либы. i2c завтра скину примеры.
        Ну и общее, F0 это не те Мк чтобы использовать визуальные тыкалки и
        достаточно сырые, глючные либы.
        Я понимаю что вам сложно освоиться и тяжело дается изучение железа, но лиха беда начала. Если есть желание-помогу, нет -как хотите.

        На счет блютуз, это все конечно хорошо и удобно, но вы не думали о WiFi ? На тех же esp8266 есть вкусные прошивки modbus TCP.
        Плюсы очевидны, особенно для клиентов. Физически изменений ноль, такой же модуль и связь USART.

  4. Здесь работа с i2c, останется только добавить обработку ошибок.

    void i2c_init(void)
    {
    RCC->AHBENR |= RCC_AHBENR_GPIOBEN;

    RCC->APB1ENR |= RCC_APB1ENR_I2C1EN;
    RCC->CFGR3 |= RCC_CFGR3_I2C1SW;

    GPIOB->AFR[0] |= (1<<(4*6)) |(1<MODER &= ~(GPIO_MODER_MODER6 |GPIO_MODER_MODER7);
    GPIOB->MODER |= (GPIO_MODER_MODER6_1 |GPIO_MODER_MODER7_1);
    GPIOB->OTYPER |=(GPIO_OTYPER_OT_6 |GPIO_OTYPER_OT_7);

    I2C1->TIMINGR = (uint32_t)0x00B01A4B;
    I2C1->CR1 = I2C_CR1_PE;

    }

    void eeprom_pagewrite(uint16_t address, uint8_t *buf,uint8_t nbytes)
    {
    uint8_t index=0;
    I2C1->CR2 = I2C_CR2_AUTOEND | ((2+nbytes)<<16) | (EEPROM_OWN_ADDRESS<ISR & I2C_ISR_TXE) );

    I2C1->TXDR =(uint8_t) (address>>8); /* Byte to send */
    I2C1->CR2 |= I2C_CR2_START; /* Go */

    while (!(I2C1->ISR & I2C_ISR_TXIS) );
    I2C1->TXDR = (uint8_t)(address &0x00FF); /* Byte to send */
    for(index=0;indexISR & I2C_ISR_TXIS) );

    I2C1->TXDR = buf[index] ; /* Byte to send */
    }
    }

    void eeprom_pageread(uint16_t address,uint8_t* buf,uint8_t nbytes)
    {

    uint8_t index=0;
    I2C1->CR2 = (2<<16) | (EEPROM_OWN_ADDRESS<ISR & I2C_ISR_TXE) );
    I2C1->TXDR = (uint8_t) (address>>8); /* Byte to send */
    I2C1->CR2 |= I2C_CR2_START; /* Go */
    while (!(I2C1->ISR & I2C_ISR_TXIS) );
    I2C1->TXDR = (uint8_t)(address &0x00FF); /* Byte to send */
    while (!(I2C1->ISR & I2C_ISR_TC) ){};
    I2C1->CR2 = I2C_CR2_AUTOEND |
    (nbytes<<16) |
    (EEPROM_OWN_ADDRESS<CR2 |= I2C_CR2_START; /* Go */
    for(index=0;indexISR & I2C_ISR_RXNE) ){};
    buf[index] = I2C1->RXDR ;

    }
    }
    void rda5807_send_reg(uint8_t reg, uint8_t data_h,uint8_t data_l)
    {
    I2C1->CR2 = I2C_CR2_AUTOEND | (3<<16) | (RDA5807_OWN_ADDRESS<ISR & I2C_ISR_TXE) );

    I2C1->TXDR = reg; /* Byte to send */
    I2C1->CR2 |= I2C_CR2_START; /* Go */

    while (!(I2C1->ISR & I2C_ISR_TXIS) );
    I2C1->TXDR = data_h; /* Byte to send */
    while (!(I2C1->ISR & I2C_ISR_TXIS) );

    I2C1->TXDR = data_l; /* Byte to send */

    }
    uint16_t rda5807_read16_reg(uint8_t reg)
    {
    uint16_t temp=0;
    I2C1->CR2 = (1<<16) | (RDA5807_OWN_ADDRESS<ISR & I2C_ISR_TXE) );
    I2C1->TXDR = reg; /* Byte to send */
    I2C1->CR2 |= I2C_CR2_START; /* Go */
    while (!(I2C1->ISR & I2C_ISR_TC) ){};
    I2C1->CR2 = I2C_CR2_AUTOEND | (2<<16) |
    (RDA5807_OWN_ADDRESS<CR2 |= I2C_CR2_START; /* Go */
    while (!(I2C1->ISR & I2C_ISR_RXNE) ){};
    temp = (uint16_t)(I2C1->RXDR <ISR & I2C_ISR_RXNE) ){};
    temp |= (uint16_t)I2C1->RXDR;
    return temp;
    }

    void ssd1306_SendData(uint8_t *data, uint8_t count)
    {
    uint8_t index=0;
    I2C1->CR2 = I2C_CR2_AUTOEND | ((1+count)<<16) | (SSD1306_OWN_ADDRESS<ISR & I2C_ISR_TXE) );

    I2C1->TXDR = SSD1306_DATA_MODE;
    I2C1->CR2 |= I2C_CR2_START;

    for(index=0;indexISR & I2C_ISR_TXIS) );

    I2C1->TXDR = *data++ ; /* Byte to send */
    }
    }

    void ssd1306_send(uint8_t control_byte, uint8_t data)
    {
    I2C1->CR2 = I2C_CR2_AUTOEND | (2<<16) | (SSD1306_OWN_ADDRESS<ISR & I2C_ISR_TXE) );

    I2C1->TXDR = control_byte;
    I2C1->CR2 |= I2C_CR2_START;

    while (!(I2C1->ISR & I2C_ISR_TXIS) );
    I2C1->TXDR = data;
    }

    • У меня кстати другой вопрос. Вы когда-нибудь USART в синхронном режиме использовали? Т.е. с клоком. Мне надо только на прием. Там нет никаких подводных камней? Я думаю использовать ли USART или сделать на EXTI, скорость порядка 1 кГц, медленная но не постоянная.

      • Работал но на передачу, эмулировал SPI. Все работало. Что с передающей стороны будет?

      • Спасибо! Уже сделал, как вы говорите с помощью “ногодрыга”, т.е. на внешних прерываниях)))
        С тои стороны мышка ps/2

  5. Здравствуйте!
    Спасибо большое за код и за ваши мысли. Что-то в этом есть. 🙂
    Попробую протестировать при первой возможности.

    • Не за что, есть еще много чего.
      Ну 1wire через USART с DMA , вы наверное уже знаете.
      Есть полностью аппаратная динамическая LED индикация .

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s