Ви не увійшли.
Сторінки 1
А в реальности, по тестам, реле одного и того же производителя: от очень плохо, до вполне приемлемо. Реле Songle SRD-05VDC-SL-C - два реле (в модуле для Ардуино) выдержали около 1000 переключений и стали переключаться через раз, а другие и после 20 000 не выдавали ни одной ошибки. Стоит отметить, что корпус бракованных реле - более светлый, а у тех, что работают хорошо - темнее. Так что помимо модели, нужно учитывать подделки.
Также, если планируете тестить реле - тестируйте их под реальной нагрузкой, хотя бы под половниинной предельной мощностью. Я тестировал практически без нагрузки, через контактные площадки реле проходило 5В и несколько мкА! У меня тест реле скорее на программирование, чем на реальную тестовую лабораторию (схема), но если её немного "допилить" (схему), то можно тестировать по настоящему.
Здравствуйте.
Подскажите, сколько, приблизительно раз можно заливать скетч в Mega2560 до выхода из строя флеша, на котором хранится скетч? Вопрос возник из-за того, что например у EEPROM есть гарантированное кол-во циклов записи ячейки памяти, 100 000, а вот "изнашивается" ли флеш, в который заливаются скетчи?
Спасибо за оценку, но от улучшений этого скрипта я откажусь, так как есть на что потратить время, да и как по мне, интереснее выводить не на терминал, а через web-сервер. Этим скриптом я учился работать со структурами.
А по поводу лампочки - её можно взять из первого скрипта: функция mk_led_blink() как раз и задумывалась для индикации работы: интегрированный в дуину led медленно мигает, когда идет процесс без ошибок, быстро - если ошибка, и просто светит, если тест закончился без ошибок.
Переписал скрипт с использованием структур. Все протестировал - работает: определяет, если после сигнала на переключение реле не произошло переключение контактов, и в этом случае заносит это событие в счетчик ошибок. Надеюсь, этот код кому-нибудь пригодится для теста реле или изучения работы структур
Просьба покритиковать код, возможно что-то можно было бы улучшить/оптимизировать? Для всех ли переменных объявлены правильные типы?
Из того, что я бы сделал сам, да не знаю как:
- заменить строку relay_data *relay_arr[] = {d_relay_1, d_relay_2}, в которой массивы собираются в один, каким-нибудь автоматическим процессом, чтобы в случае добавления/отключения релешек не нужно было править эту строку вручную.
Код скрипта проверки реле:
// Тест реле
// Константы
#define SERIAL_MONITOR_SW 1 // Включен (1) или выключен (0) Serial Monitor
#define SERIAL_MONITOR_SPEED 57600 // Скорость работы Serial Monitor
#define RELAY_SWITCH_MAX 20UL // Кол-во включений/выключений реле
#define RELAY_SWITCH_DELAY 500UL // Скорость работы переключения реле - пауза между переключениями в мс
#define RELAY_OFF_DEFAULT HIGH // Состояние выключенного реле (HIGH|LOW)
#define SERIAL_FREQ 5000UL // Пауза в мс между выводами информации в Serial Monitor
// Структура параметров реле
struct relay_data
{
byte pin_relay_control; // Номер выхода управления реле
byte pin_relay_contact; // Номер входа для чтения показаний с контакта реле
unsigned long interval_sw; // Таймер интервала переключения реле
unsigned long interval_sw_timer; // Интервал переключения реле
unsigned long sw_counter; // Счетчик кол-ва переключений реле
byte status_control; // Статус управления реле. LOW - включить, HIGH - отключить реле
byte status_contact; // Статус контакта реле. LOW - нет сигнала, HIGH - есть сигнал
byte sw_status_counter; // Счетчик изменения статусов
unsigned long error_counter; // Общее кол-во ошибок
unsigned long error_counter_on; // Кол-во ошибок включения
unsigned long error_counter_off; // Кол-во ошибок выключения
};
// Параметры по умолчанию для реле 1 (последовательность согласно структуре в struct)
relay_data d_relay_1[1] =
{
{22,30,500,0,0,RELAY_OFF_DEFAULT,HIGH,2,0,0,0},
};
relay_data &relay_1 = d_relay_1[0];
// Параметры по умолчанию для реле 2 (последовательность согласно структуре в struct)
relay_data d_relay_2[1] =
{
{23,31,550,0,0,RELAY_OFF_DEFAULT,HIGH,2,0,0,0},
};
relay_data &relay_2 = d_relay_2[0];
relay_data *relay_arr[] = {d_relay_1, d_relay_2};
byte relay_count = sizeof(*relay_arr);
void setup()
{
if (SERIAL_MONITOR_SW == 1)
{
Serial.begin(SERIAL_MONITOR_SPEED);
Serial.println("Relay tester");
Serial.println();
Serial.print("Count relay for test: ");
Serial.println(relay_count);
Serial.println();
Serial.println("SETUP: set in/out pin:");
}
for (int i = 0; i < relay_count; i++)
{
relay_data &rel_cur_arr = *relay_arr[i];
pinMode(rel_cur_arr.pin_relay_control, OUTPUT);
digitalWrite(rel_cur_arr.pin_relay_control, RELAY_OFF_DEFAULT);
pinMode(rel_cur_arr.pin_relay_contact, INPUT);
if (SERIAL_MONITOR_SW == 1)
{
Serial.print("Relay ");
Serial.print((i + 1));
Serial.print(": pin_relay_control-");
Serial.print(rel_cur_arr.pin_relay_control);
Serial.print("; pin_relay_contact-");
Serial.print(rel_cur_arr.pin_relay_contact);
Serial.println(".");
}
}
// pinMode(PIN_MK_LED, OUTPUT);
}
void loop()
{
relay_test();
relay_data_serial();
}
// Функция тестирования реле
void relay_test()
{
for (int i = 0; i < relay_count; i++)
{
relay_data &rel_cur_arr = *relay_arr[i];
if (rel_cur_arr.sw_counter <= RELAY_SWITCH_MAX)
{
if (millis() - rel_cur_arr.interval_sw_timer > rel_cur_arr.interval_sw)
{
rel_cur_arr.interval_sw_timer = millis();
//Serial.print(rel_cur_arr.pin_relay_control);
//Serial.print(" - ");
//Serial.print(rel_cur_arr.sw_status_counter);
//Serial.println("");
// Счетчик ошибок
if (rel_cur_arr.sw_status_counter < 2)
{
rel_cur_arr.error_counter++;
if (rel_cur_arr.status_control == RELAY_OFF_DEFAULT)
rel_cur_arr.error_counter_off++;
else
rel_cur_arr.error_counter_on++;
}
rel_cur_arr.sw_status_counter = 0;
// Включение/отключение реле
if (rel_cur_arr.sw_counter == RELAY_SWITCH_MAX) // Отключение реле после отработки максимального кол-ва переключений
rel_cur_arr.status_control = RELAY_OFF_DEFAULT;
else // Изменение состояния реле (Вкл/Выкл)
rel_cur_arr.status_control = !rel_cur_arr.status_control;
digitalWrite(rel_cur_arr.pin_relay_control, rel_cur_arr.status_control);
rel_cur_arr.sw_counter++;
}
// Проверка состояний контактов
rel_cur_arr.status_contact = digitalRead(rel_cur_arr.pin_relay_contact);
if (rel_cur_arr.status_contact == LOW)
rel_cur_arr.sw_status_counter = 1;
if (rel_cur_arr.status_contact == HIGH && rel_cur_arr.sw_status_counter == 1)
rel_cur_arr.sw_status_counter = 2;
}
}
}
// Функция вывода информации о результатах тестирования реле в Serial Monitor
void relay_data_serial()
{
if (SERIAL_MONITOR_SW == 1)
{
static unsigned long interval_timer = 0;
static byte relay_num = 0;
static byte reley_test_end_counter = 0;
static byte reley_test_end = 0;
if (millis() - interval_timer > SERIAL_FREQ && reley_test_end == 0)
{
Serial.println();
interval_timer = millis();
for (int i = 0; i < relay_count; i++)
{
relay_data &rel_cur_arr = *relay_arr[i];
// Поиск окончания проверки
if (rel_cur_arr.sw_counter >= RELAY_SWITCH_MAX)
reley_test_end_counter++;
relay_num = i + 1;
Serial.print("Relay ");
Serial.print(relay_num);
Serial.print(" (pin control ");
Serial.print(rel_cur_arr.pin_relay_control);
Serial.println("):");
Serial.print("On/off switch: ");
Serial.print((rel_cur_arr.sw_counter - 1));
Serial.print("; Error counters On: ");
Serial.print(rel_cur_arr.error_counter_on);
Serial.print(", Off: ");
Serial.print(rel_cur_arr.error_counter_off);
Serial.println();
}
if (reley_test_end_counter > relay_count)
reley_test_end = 1;
}
}
}
volatile если в несколько потоков будете работать ( вероятно не ваш вариант )
думаю Вам проще работать с глобальной переменной ,чем в функции изменять данные по указателю.
доступ к данным
error_status.error_counter++;для экономии времени запускайте тест на всех реле реле одновременно, а анализ и выдачу результата только по тем ножка (вход) которые нужны.
я бы так делал."2. Как перезаписывать в переменную текстовые данные? Я сделал попытку, записывать в переменную relay_status значения ON|OFF, но из этого ничего не получилось: или ошибка, или все время выводится OFF." не совсем понятно, что Вы имеете в виду?
Спасибо, что откликнулись! Не подскажете, где можно подробнее почитать про указатели и voliate с несколькими потоками? Или примеры реализации скриптов?
А по поводу перезаписи текстовых данных: хотелось бы выводить текст статуса реле (ON|OFF), а не 1 и 0... Для этого, я и предполагал использовать переменную, которую если реле включено записывается "ON", выключено - "OFF".
Здравствуйте.
В целях обучения программированию на Ардуино написал скрипт проверки электромеханических реле. Код - работает, т.е. вполне можно проверить работоспособность ОДНОГО реле.
Суть проверки: реле с заданным интервалом включается/отключается, МК проверяет наличие сигнала, проходящего через контакты электромеханического реле. Результаты проверки, пока что, можно смотреть только через Serial Monitor.
На создание скрипта натолкнула обнаруженная неисправность в китайских реле, которые проработали от силы 1000 включений (Бракованные реле Songle 10А отличается по цвету (немного светлее) от тех, что работают без сбоев).
Просьба помочь усовершенствовать скетч, чтобы можно было при помощи одной функции проверять более одного реле.
Также, есть такие вопросы:
1. Как вывести из функции данные о более чем 1-ом параметре (кол-во ошибок при включении, кол-во ошибок при выключении, и др.). Я вижу несколько способов: глобальные переменные, массив. Что правильнее, и если массив - то как это реализовать?
2. Как перезаписывать в переменную текстовые данные? Я сделал попытку, записывать в переменную relay_status значения ON|OFF, но из этого ничего не получилось: или ошибка, или все время выводится OFF.
Буду признателен за любую помощь!
Код скрипта:
// Тест реле
// Определение номеров входов и выходов
#define PIN_MK_LED 13 // Светодиод интегрированный в Ардуино
#define PIN_RELAY_1_SW 22 // Управление реле 1
#define PIN_RELAY_2_SW 23 // Управление реле 2
#define PIN_RELAY_1_CONTACT 30 // Вход с контакта реле 1
#define PIN_RELAY_2_CONTACT 31 // Вход с контакта реле 2
// Другие константы
#define SERIAL_MONITOR_SW 1 // Включен (1) или выключен (0) Serial Monitor
#define SERIAL_MONITOR_SPEED 57500 // Скорость работы Serial Monitor
#define RELAY_SWITCH_DELAY 500 // Скорость работы Serial Monitor
// Определение переменных
// Светодиод интегрированный в Ардуино
unsigned long mk_led_interval_on = 200; // мс
unsigned long mk_led_interval_off = 800; // мс
void setup()
{
if (SERIAL_MONITOR_SW == 1)
Serial.begin(SERIAL_MONITOR_SPEED);
pinMode(PIN_MK_LED, OUTPUT);
pinMode(PIN_RELAY_1_SW, OUTPUT);
pinMode(PIN_RELAY_1_CONTACT, INPUT);
digitalWrite(PIN_RELAY_1_SW, LOW);
}
void loop()
{
// Светодиод мигает - МК работает
mk_led_blink(mk_led_interval_on, mk_led_interval_off);
relay_test(PIN_RELAY_1_SW, PIN_RELAY_1_CONTACT, RELAY_SWITCH_DELAY);
//relay_test(PIN_RELAY_2_SW, PIN_RELAY_2_CONTACT, RELAY_SWITCH_DELAY);
}
// Тест реле
void relay_test(byte pin_switch, byte pin_contact, unsigned long interval)
{
static unsigned long interval_timer = 0; // Интервал переключения
static unsigned long sw_delay_timer = 0; //
static unsigned long sw_delay = 0; //
static unsigned long sw_counter = 0; //
static byte sw_status = LOW;
static byte cont_expected_status = LOW;
static byte cont_real_status = 0;
static char relay_status[] = "OFF";
static byte error = 0;
static unsigned long error_counter = 0;
static unsigned long error_counter_on = 0;
static unsigned long error_counter_off = 0;
if (millis() - interval_timer > interval)
{
sw_counter++;
error = 0;
if (sw_delay_timer > 0)
{
error_counter++;
error = 1;
if (sw_status == HIGH)
error_counter_on++;
else
error_counter_off++;
}
if (SERIAL_MONITOR_SW == 1)
{
Serial.print("Relay pin: ");
Serial.print(pin_switch);
Serial.println(";");
Serial.print("contact pin: ");
Serial.print(pin_contact);
Serial.println(";");
Serial.print("relay status: ");
Serial.print(sw_status);
Serial.println(";");
Serial.print("error: ");
Serial.print(error);
Serial.println(";");
Serial.print("TOTAL: ON/OFF relay counter - ");
Serial.print(sw_counter);
Serial.print("; error ON - ");
Serial.print(error_counter_on);
Serial.print("; error OFF - ");
Serial.print(error_counter_off);
Serial.println();
Serial.println();
}
interval_timer = millis();
if (sw_status == LOW)
{
sw_status = HIGH;
char relay_status[] = "ON";
}
else
{
sw_status = LOW;
char relay_status[] = "OFF";
}
digitalWrite(pin_switch, !digitalRead(pin_switch));
}
if (digitalRead(pin_contact) == LOW && sw_delay_timer == 0)
{
sw_delay_timer = millis();
}
if (digitalRead(pin_contact) == HIGH && sw_delay_timer > 0)
{
sw_delay = millis() - sw_delay_timer;
sw_delay_timer = 0;
}
}
// Светодиод мигает - МК работает
// interval_on .... - кол-во милисекунд, на которое будет включен светодиод
// interval_off ... - кол-во милисекунд, на которое будет выключен светодиод
void mk_led_blink(unsigned long interval_on, unsigned long interval_off)
{
static unsigned long mk_led_switch_interval = 0; // Интервал переключения
static unsigned long mk_led_switch_timer = 0; // Время когда последний раз переключали диод
static byte mk_led_status = LOW; //
if (millis() - mk_led_switch_timer > mk_led_switch_interval)
{
mk_led_switch_timer = millis();
if (mk_led_status == LOW)
{
mk_led_status = HIGH;
mk_led_switch_interval = interval_on;
}
else
{
mk_led_status = LOW;
mk_led_switch_interval = interval_off;
}
digitalWrite(PIN_MK_LED, mk_led_status);
}
}
Схема упрощена, к Ардуино реле подключено не напрямую - подключен модуль реле на оптопаре. Подключив реле напрямую к МК, как указано на схеме, ВЫ рискуете спалить вывод МК!
R1-R2 10K
Сторінки 1