Ну вот, устройство собрано. Все, наконец, заработало. Сбоев нет. Всем спасибо за помощь и советы! Но вот какие «смутные сомнения».
- Во многих постах сообщалось, что на входе пинов Ардуино УЖЕ стоят триггеры, поэтому для убивания дребезга достаточно закоротить кнопку (или выводы энкодера) RC-цепочкой. В моем случае это оказалось не так. RC-цепочки ни «от балды» ни рассчитанная не спасали. Стоило же только между Мегой и кнопкой поставить триггер (SN74HC14N), как эффект дребезга исчез. RC-цепочку на кнопке, естественно, оставил. Так что, все-таки, нету триггеров в Ардуине?
- После загрузки скетча с ПК устройство сразу начинает выполнять программу. Если же отключить его от ПК и запитать от внешнего источника, то сначала на одном из трех индикаторов max7219 (в скетче он обозначен как “lc_val”) кратковременно зажигаются все восьмерки с точками. Потом индикатор гаснет, и устройство приступает к выполнению программы. Это не сильно парит, но неприятно. Проблема в скетче или чисто аппаратная (типа где-то дребезг или что-то иное)? Есть ли какой-то способ избежать (или победить) это нештатное вспыхивание индикатора?
На всякий случай привожу сам скетч.
//Mega2560
/*Пины прерываний
пин2 (прерывание 0)
пин3 (прерывание 1)
пин18 (прерывание 5)
пин19 (прерывание 4)
пин20 (прерывание 3)
пин21 (прерывание 2)*/
//Пины термодатчика колонны
int pin_col = 47; //Пин термодатчика колонны 47
int pin_col_vcc = 49; //Пин 5v термодатчика колонны 49
int pin_col_gnd = 45; //Пин gnd термодатчика колонны 45
//Пин клапана
int pin_val = 12; //Пин клапана
//Переменные
//Температура колонны
volatile int temp_col; // Температура ректификационной колонны
unsigned long ds18b20_time; //Переменная периода опроса термодатчиков
//Температура отсечки
volatile int temp_adj; // Температура отсечки хвостов
volatile int but_adj = 0; // Значение кнопки отсечки
//Работа клапана
volatile long val_interval = 1000; // Время закрытого клапана, умноженное на 1000 (открытый всегда на 1000 мсек)
volatile long val_change = 1; // Данные энкодера клапана
volatile int but_val; // Значение кнопки клапана
volatile int flag_val = 0; // Включать или нет клапан
int val_state = LOW; // Состояние клапана
long previousMillis = 0; // храним время последнего переключения кларана
int flag_val_temp = 0; // Состояние отсечки хвостов
int sot; //Для интикаторов сотни
int des; //Для интикаторов десятки
int edi; //Для интикаторов единицы
volatile int clk; //Состояние пина прерывания энкодера
volatile int dt; //Состояние второго пина энкодера
volatile int sw; //Состояние пина пина прерывания кнопки
//Подключение библиотеки термодатчика колонны
#include <OneWire.h>
OneWire ds_col(pin_col); // Датчик T° колонны на пине 47
//Подвязывание рабочих переменных к библиотеке датчика
byte i;
byte present = 0;
byte data[12];
byte addr_col[8];
//Подключение библиотеки max7219
#include <LedControl.h>
//создаём объект класса LedControl (din,clk,cs,X) X - количество модулей
//Провода: clk-зеленый, cs-желтый, din-оранжевый
LedControl lc_col = LedControl(30, 34, 32, 1);
LedControl lc_adj = LedControl(38, 42, 40, 1);
LedControl lc_val = LedControl(46, 50, 48, 1);
// Массив с закодированными символами для надписей.
byte bukvy[12] =
{
B01001110, //C-0
B00011101, //o-1
B00001100, //l-2
B01110111, //A-3
B00111101, //d-4
B00011000, //j-5
B01100011, //°-6
B01111110, //O-7
B01000111, //F-8
B00010101, //n-9
B00000000, //пусто-10
B00000001, //тире-11
};
void setup()
{
Serial.begin(115200);// Объявляем скорость порта
//Инициализация пина клапана
pinMode(pin_val, OUTPUT); //Пин клапана на выход
//Инициализация пинов датчика колонны
pinMode(pin_col, INPUT); //Пин термодатчика колонны на вход
pinMode(pin_col_vcc, OUTPUT); //Пин 5v термодатчика колонны на выход
digitalWrite (pin_col_vcc, HIGH);
pinMode(pin_col_gnd, OUTPUT); //Пин gnd термодатчика колонны на выход
digitalWrite (pin_col_gnd, LOW);
//Запрос термодатчику колонны на измерение температуры
if ( !ds_col.search(addr_col)) {}
//Инициируем датчик температуры колонны
ds_col.reset();
ds_col.select(addr_col);
ds_col.write(0x44);
//Назначение пинов индикаторов на выход
for (int ind = 30; ind <= 50; ind++)
{
pinMode(ind, OUTPUT);
}
//Инициализация модулей индикаторов
lc_col.shutdown(0, false); //Выводим из спящего режима
lc_col.setIntensity(0, 7); //Яркость дисплея на 7. Всего возможных режимов яркости от 0 до 15
lc_col.clearDisplay(0); //Очистить дисплей
lc_adj.shutdown(0, false); //Выводим из спящего режима
lc_adj.setIntensity(0, 7); //Яркость дисплея на 7. Всего возможных режимов яркости от 0 до 15
lc_adj.clearDisplay(0); //Очистить дисплей
lc_val.shutdown(0, false); //Выводим из спящего режима
lc_val.setIntensity(0, 7); //Яркость дисплея на 7. Всего возможных режимов яркости от 0 до 15
lc_val.clearDisplay(0); //Очистить дисплей
//Тест №1
//Пишем цифры от 0 до 7
for (int dig = 7; dig >-1; dig--)
{
lc_col.setDigit(0, dig, 7-dig, false);
delay (150);
}
delay (150);
for (int dig = 7; dig >-1; dig--)
{
lc_adj.setDigit(0, dig, 7-dig, false);
delay (150);
}
delay (150);
for (int dig = 7; dig >-1; dig--)
{
lc_val.setDigit(0, dig, 7-dig, false);
delay (150);
}
delay (150);
//Очищаем индикаторы
lc_col.clearDisplay(0); //Очистить дисплей
lc_adj.clearDisplay(0); //Очистить дисплей
lc_val.clearDisplay(0); //Очистить дисплей
//Проверяем восьмерки
for (int dig = 7; dig >-1; dig--) //Восьмерки в левом индикаторе
{
lc_col.setDigit(0, dig, 8, true);
delay (75);
lc_col.clearDisplay(0); //Очистить дисплей
}
for (int dig = 7; dig >-1; dig--) //Восьмерки в среднем индикаторе
{
lc_adj.setDigit(0, dig, 8, true);
delay (75);
lc_adj.clearDisplay(0); //Очистить дисплей
}
for (int dig = 7; dig >-1; dig--) //Восьмерки в правом индикаторе
{
lc_val.setDigit(0, dig, 8, true);
delay (75);
lc_val.clearDisplay(0); //Очистить дисплей
}
delay (200);
//Пишем "Col"
lc_col.setRow(0, 7, bukvy[0]);//Индикация C"
lc_col.setRow(0, 6, bukvy[1]);//Индикация "o"
lc_col.setRow(0, 5, bukvy[2]);//Индикация "l"
lc_col.setRow(0, 0, bukvy[6]);//Индикация "°"
//Пишем "Adj"
lc_adj.setRow(0, 7, bukvy[3]);//Индикация "A"
lc_adj.setRow(0, 6, bukvy[4]);//Индикация "d"
lc_adj.setRow(0, 5, bukvy[5]);//Индикация "j"
lc_adj.setRow(0, 0, bukvy[6]);//Индикация "°"
//Пишем "OFF"
lc_val.setRow(0, 7, bukvy[7]);//Индикация "O"
lc_val.setRow(0, 6, bukvy[8]);//Индикация "F"
lc_val.setRow(0, 5, bukvy[8]);//Индикация "F"
lc_val.setDigit(0, 3, 1, false); //Индикация "1"
lc_val.setRow(0, 2, bukvy[11]);//Индикация "-"
//Назначение пинов чтения энкодера и кнопок на вход
for (int ind = 16; ind < 22; ind++)
{
pinMode(ind, INPUT); //пины на вход
}
//Назначение прерываний
attachInterrupt(5, BUTTON_ADJ, FALLING); //пин прерывания кнопки отсечки хвостов
attachInterrupt(4, ENCODER_ADJ, FALLING); //пин прерывания энкодера отсечки хвостов
attachInterrupt(3, BUTTON_VAL, FALLING); //пин прерывания кнопки клапана
attachInterrupt(2, ENCODER_VAL, FALLING); //пин прерывания энкодера клапана
Serial.begin(115200);// Объявляем скорость порта
}
void loop()
{
//Опрос показаний датчика температуры колонны 1 раз в 850 мсек
if (millis() - ds18b20_time > 850)
//Опрашиваем датчик колонны
present = ds_col.reset();
ds_col.select(addr_col);
ds_col.write(0xBE);
for ( i = 0; i < 9; i++)
{
data[i] = ds_col.read();
}
int16_t raw = (data[1] << 8) | data[0];
temp_col = raw / 1.6;
//Очередной запрос термодатчику колонны на измерение температуры
if ( !ds_col.search(addr_col)) {}
//Инициируем датчик температуры колонны
ds_col.reset();
ds_col.select(addr_col);
ds_col.write(0x44);
//Раскладка данных температуры колонны и индикация
sot = temp_col / 100;
des = temp_col % 100 / 10;
edi = temp_col % 10;
lc_col.setDigit(0, 3, sot, false);
lc_col.setDigit(0, 2, des, true);
lc_col.setDigit(0, 1, edi, false);
//Раскладка данных температуры отсечки и индикация
if (temp_adj > 999) {
temp_adj = 999; //Предел 999
}
if (temp_adj < 0) {
temp_adj = 0; //Предел 0
}
sot = temp_adj / 100;
des = temp_adj % 100 / 10;
edi = temp_adj % 10;
lc_adj.setDigit(0, 3, sot, false);
lc_adj.setDigit(0, 2, des, true);
lc_adj.setDigit(0, 1, edi, false);
//Раскладка данных клапана
if (flag_val == 0)
{
lc_val.setRow(0, 7, bukvy[7]);//Индикация "O"
lc_val.setRow(0, 6, bukvy[8]);//Индикация "F"
lc_val.setRow(0, 5, bukvy[8]);//Индикация "F"
}
if (flag_val == 1)
{
lc_val.setRow(0, 7, bukvy[7]);//Индикация "O"
lc_val.setRow(0, 6, bukvy[9]);//Индикация "n"
lc_val.setRow(0, 5, bukvy[10]);//Индикация "_"
}
if (val_change > 59) {
val_change = 59; //Предел 59
}
if (val_change < 1) {
val_change = 1; //Предел 1
}
des = val_change % 100 / 10;
edi = val_change % 10;
lc_val.setDigit(0, 1, des, false);
lc_val.setDigit(0, 0, edi, false);
//Работа клапана
if(temp_col>temp_adj) //Если температура колонны выше температуры отсечки
{
flag_val_temp=0;
lc_val.setChar (0,4,' ', false);
}
else //Если температура колонны ниже температуры отсечки
{flag_val_temp=1;
lc_val.setChar (0,4,' ', true);
}
unsigned long currentMillis = millis(); // Приравниваем время отслеживания к таймеру
if (currentMillis - previousMillis > val_interval) //Если прошел нужный интервал
{
previousMillis = currentMillis; // сохраняем время последнего переключения
if (flag_val == 1 && flag_val_temp == 1) //если разрешено работать клапану
{
// если клапан закрыт, то открываем, и наоборот
if (val_state == LOW)
{
val_state = HIGH;
val_interval = 1000;
}
else
{
val_state = LOW;
val_interval = val_change * 1000;
}
digitalWrite(pin_val, val_state);// устанавливаем состояния выхода, чтобы включить или выключить клапан
}
else {digitalWrite(pin_val, LOW);} // если запрещено работать клапану
}
Serial.println (flag_val); //Вывод на монитор
}
void ENCODER_ADJ() //Читаем энкодер отсечки
{
clk = digitalRead(19);
dt = digitalRead(16);
if (clk < dt) {
temp_adj++;
}
else {
temp_adj--;
}
}
void BUTTON_ADJ() //Читаем кнопку отсечки
{
but_adj++;
if (but_adj == 1) {
temp_adj = temp_col;
}
if (but_adj == 2) {
temp_adj = 999;
}
if (but_adj == 3) {
but_adj = 0;
}
}
void ENCODER_VAL() //Читаем энкодер клапана
{
clk = digitalRead(20);
dt = digitalRead(17);
if (clk < dt) {
val_change--;
}
else {
val_change++;
}
}
void BUTTON_VAL() //Читаем кнопку клапана
{
if (flag_val == 0) {
flag_val = 1;
}
else {
flag_val = 0;
}
}