Найти в Дзене
Dexter's Lab

АВТОМАТИЧЕСКОЕ УПРАВЛЕНИЕ СУШИЛКАМИ УГЛЯ на базе ARDUINO (Часть 5)

Вы читаете очередную статью об автоматическом управлении сушильными камерами, где я подробно описываю реализацию одного из наших заказов. Начало здесь, здесь, здесь и здесь. Продолжаем говорить собственно о программном коде нашего устройства. Язык в среде Arduino схож с Си. Помочь освоить Си мне помог учебник Солдатенко И.С. "Основы программирования на языке Си". В освоении языка среды Arduino помогают многочисленные статьи и примеры кода для работающих устройств, выложенные в Интернет. В шапку главного файла Drying_Shop_Script.ino я поместил все библиотеки, которые я использую в работе сушилок: #include <Arduino.h> #include <locale.h> #include <Wire.h> // обязательные библиотеки #include <GyverTimers.h> // библиотека с таймерами Гайвера. Таймеры мне нужны для распределения задач, выполняемых микроконтроллером. Периодически (один раз в 4,2 секунды) выполняется основной скрипт, опрашиваются датчики один за другим. Если находится ошибка в данных датчиков, сохраняемся в EEPROM, уходим в

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

Продолжаем говорить собственно о программном коде нашего устройства. Язык в среде Arduino схож с Си. Помочь освоить Си мне помог учебник Солдатенко И.С. "Основы программирования на языке Си". В освоении языка среды Arduino помогают многочисленные статьи и примеры кода для работающих устройств, выложенные в Интернет.

В шапку главного файла Drying_Shop_Script.ino я поместил все библиотеки, которые я использую в работе сушилок:

#include <Arduino.h>

#include <locale.h>

#include <Wire.h> // обязательные библиотеки

#include <GyverTimers.h> // библиотека с таймерами Гайвера. Таймеры мне нужны для распределения задач, выполняемых микроконтроллером. Периодически (один раз в 4,2 секунды) выполняется основной скрипт, опрашиваются датчики один за другим. Если находится ошибка в данных датчиков, сохраняемся в EEPROM, уходим в перезагрузку. Значит, мне нужна библиотека работы с EEPROM, добавляю:

#include <EEPROM.h>

Второй таймер запускает скрипт меню, отражённого на дисплее 20х04.

Третий таймер запускает скрипт компрессора.

#include <LiquidCrystal_I2C.h> // библиотека для работы по протоколу I2С с дисплеем 20х04 с нужными мне русскими символами

LiquidCrystal_I2C lcd(0x3F, 20, 4); // мой дисплей (20 символов, 4 строки) нашёлся по адресу 0х3F

#define cols 20 #define rows 4 // содержит по 20 символов в 4 строках

#include <U8glib.h> // библиотека для работы с дисплеем 128х64

#include "rus5x8.h" // файл с русским шрифтом с буквами размером 5х8 пикселей, для дисплея 128х64

U8GLIB_ST7920_128X64_1X u8g(13, 11, 12); // согласно библиотеке подключил дисплей к пинам 13, 11, 12 на плате Arduino

#include "DHT.h"

#include "sensors.h"

#include "variables.h"

#include "rus.h"

#include "menu.h"

#include "cat.h" // это вспомогательные файлы, о них я рассказал ранее

Теперь функции:

void draw_(void) {

u8g.drawXBM( 0, 0, 128, 64, u8g_cat_bits);

} // функция с котом - рисуем кота в заставке (из файла cat.h). Кот появится ненадолго только при старте системы.

void draw(void) {

// функция рисования таблицы на экране 128х64, вот этой:

Готовимся заполнить таблицу на экране 128х64 данными из массива с переменными, которые сохраняются у меня в файле variables.h. Для примера я привожу здесь код только для одной комнаты:

char ct_1[5]; // переменная о значением температуры в данный момент (ct - current temperature)

String str_ct_1; // строка со значением этой переменной

str_ct_1=String(cur_temp_1);

str_ct_1.toCharArray(ct_1,5);

Всё то же самое для значения относительной влажности (current humidity) в данный момент:

char ch_1[5];

String str_ch_1;

str_ch_1=String(cur_hum_1);

str_ch_1.toCharArray(ch_1,5);

Последующие данные комнаты беру из файла variables.h:

char th_1[5]; // top humidity - верхний предел относительной влажности

String str_th_1;

str_th_1=String(dryers.top_hum_1);

str_th_1.toCharArray(th_1,5);

char dh_1[5]; // difference between humidities - диапазон между верхней и нижней границами "коридора" относительной влажности

String str_dh_1;

str_dh_1=String(dryers.dif_hum_1);

str_dh_1.toCharArray(dh_1,5);

char pd_1[5]; // percentage down - количество процентов, на которое снижаем верхнюю границу

String str_pd_1;

str_pd_1=String(dryers.perc_down_1);

str_pd_1.toCharArray(pd_1,5);

char hit_1[5]; // humidity increase time - время, в течение которого относительная влажность в комнате должна достигнуть верхнего предела при закрытой заслонке. Если этого не произошло, автоматически снижается значение верхнего предела.

String str_hit_1;

str_hit_1=String(dryers.hum_incr_time_1);

str_hit_1.toCharArray(hit_1,5);

char tt_1[5]; // temperature threshold - порог температуры, ниже которого не опускаем температуру в комнате. Заслонку больше не открываем

String str_tt_1;

str_tt_1=String(dryers.temp_thres_1);

str_tt_1.toCharArray(tt_1,5);

Используя файл с русским шрифтом, заполняю таблицу:

u8g.setFont(rus5x8);

u8g.setFontRefHeightExtendedText();

u8g.setDefaultForegroundColor();

u8g.setFontPosTop();

Заполняем "шапку" таблицы, и ещё раз о том, какие данные попадают в таблицу:

u8g.drawStr( 2, 1, "К"); // номер комнаты (сушильной камеры)

u8g.drawStr( 8, 1, "Тем"); // температура в комнате

u8g.drawStr( 26, 1, "Вла"); // относительная влажность воздуха

u8g.drawStr( 43, 1, "Вер"); // верхний предел относительной влажности

u8g.drawStr( 60, 1, "Диа"); // диапазон относительной влажности

u8g.drawStr( 77, 1, "Сни"); // значение, показывающее, на сколько процентов снизится "коридор" относительной влажности, в котором сушим уголь

u8g.drawStr( 94, 1, "Пер"); // период времени, через который будем снижать верхний предел "коридора", если относительная влажность не успела достигнуть верхнего предела

u8g.drawStr( 111, 1, "Ост"); // температура, при которой произойдёт остановка работы заслонок, уголь будет только нагреваться, сброса влажного воздуха происходить не будет.

Столбцы в таблице озаглавлены, теперь заполняем таблицу данными, подготовленными выше:

u8g.drawStr( 2, 10, "1");

u8g.drawStr( 11, 10, ct_1);

u8g.drawStr( 28, 10, ch_1);

u8g.drawStr( 45, 10, th_1);

u8g.drawStr( 62, 10, dh_1);

u8g.drawStr( 79, 10, pd_1);

u8g.drawStr( 96, 10, hit_1);

u8g.drawStr( 113, 10, tt_1);

Рисуем собственно таблицу на экране 128х64, сначала все горизонтальные линии, затем все вертикальные:

u8g.drawLine(0,0,127,0);

u8g.drawLine(0,9,127,9);

u8g.drawLine(0,18,127,18);

u8g.drawLine(0,27,127,27);

u8g.drawLine(0,36,127,36);

u8g.drawLine(0,45,127,45);

u8g.drawLine(0,54,127,54);

u8g.drawLine(0,63,127,63);

u8g.drawLine(0,0,0,127);

u8g.drawLine(7,0,7,127);

u8g.drawLine(24,0,24,127);

u8g.drawLine(41,0,41,127);

u8g.drawLine(58,0,58,127);

u8g.drawLine(75,0,75,127);

u8g.drawLine(92,0,92,127);

u8g.drawLine(109,0,109,127);

u8g.drawLine(127,0,127,127);

} // ввод функции таблицы меню на экране 128х64 завершён

На этом пока всё, в следующей статье создадим другие функции void в основном файле.