Структура программы тестера релейного модуля

IAlexandrN
Offline
Зарегистрирован: 27.11.2017

Здравствуйте.

Дано:  релейная плата, Arduino Uno (nano), I2C 1602 LCD модуль, токовый датчик и др. модули, компоненты, соелинители.

Плата с реле представляет из себя модуль с двумя группами реле, коммутирующих 3 независимых входа, с выходами. Реле управляются через 2 сдвиговых регистра 74HC594 сигналом, подаваемым с внешнего (установленного на другой плате) МК.

Задача: написать программу, для тестирования релейной платы на: срабатывание всех реле <=> прохождение сигналов с входов на выходы, отсутствие параллельного включения друго реле с адресом, отличным от заданного, контроль тока питания (кз, отсутвие потребления, низкое потребление), целостность и наличие сигнала с выхода Q7S 2-го регистра на физическом пине платы. Выводить результат на LCD дисплей (кирилица) в процессе тестирования и по окончанию тестирования (типа: "превышение потребляемого тока", "отсутствие контакта выхода 4", "тест пройден удачно").

Вопросы:

1. Что еще можно проверить на релейной плате?

2. Как вы видите алгоритм работы?

3. Какой прием можно использовать или какими должны быть ключевые функции, операторы?

 

IAlexandrN
Offline
Зарегистрирован: 27.11.2017

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Ошибся, минимум, разделом. А, скорее всего, - форумом.

IAlexandrN
Offline
Зарегистрирован: 27.11.2017

Направь.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Если на этом форуме, то раздел "Ищу исполнителя". 

IAlexandrN
Offline
Зарегистрирован: 27.11.2017

Мне не нужен готовый код, задача написать код - это моя задача, а от форума мне нужны советы как вообще такое делается. Собственно вопросы к форуму озвучены в первом сообщении.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Ну понятно. Пишется ТЗ, уточняется детали, создается проект. А дальше садитесь за компьютер и пишете код. По-моему это стандартная практика. Или вам букально на пальцах написать код за вас?

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

IAlexandrN пишет:

1. Что еще можно проверить на релейной плате?

До хрена чего можно, вопрос ведь в том "что нужно?"

IAlexandrN пишет:

2. Как вы видите алгоритм работы?

Ясно! По крайней мере пока не приму известное срецтво от DetSimen

IAlexandrN пишет:

3. Какой прием можно использовать или какими должны быть ключевые функции, операторы?

Приём - садиться и писать. Ключевые слова - http://ru.cppreference.com/w/cpp/keyword

IAlexandrN
Offline
Зарегистрирован: 27.11.2017

пишу, переписываю, уже две недели в свободную минутку... и стоя, и сидя,  и даже во сне иногда. Быстро писать не получается, и код "лосиный" на мой взгляд выходит... может задачу слишком сложную выбрал для освоения, а может сказывается то, что до этого не писал программ вообще никак и никогда.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

http://askofen.blogspot.com/2011/08/1.html Ну и так далее. И это не пустые слова.

IAlexandrN
Offline
Зарегистрирован: 27.11.2017

Что-то я не пойму общей озлобленности. Готовых программ по свою задачу я не прошу. Чей-то там кусок хлеба не отнимаю. Две недели назад получил арудуино стартер кит, поигрался с готовыми примерами, модулями. до этого  про прогрмаммирование только читал, смотрел видео. А тут знакомый предложил не просто "играть в игрушки", а продолжить своё обучение на реальном устройстве - на что я ему ответил "я на воде держаться не ммогу, а ты меня из лодки выталкиваешь и говоришь "Плыви"". Такие методы научиться плавать действенны и порой работают, правда совсем не гуманны. Вот и барахтаюсь - не плыву и не тону. Если у меня что-то получится, то кроме "молодец" я за это не получу. Лан, это всё лирика. Хотелось бы, конечно, дельных советов по моей задаче, возможно с примерами кода или ссылками на них.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Вот отсюда и смотри.#25  Это еще вариант, как написать более глюкоустойчивый код

IAlexandrN
Offline
Зарегистрирован: 27.11.2017

Ага, это те же самые классы, что и по вашей ссылке двумя постами выше. Интересно. вникаю.

...нашел ответ на будущий вопрос "как сделать, чтобы при нажатии на одну кнопку - Мк выполнял первый код, а при нажатии на другую - второй".

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

IAlexandrN пишет:

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

Пишут обычно ручками...

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

Затем составляется ТЗ. Прри этом нужно понимать, что некоторые задачт решаются исключительно программно-аппаратрыми средствами. Например, задача "контроля ток питания" чисто программными средствами не может быть решена в принципе.

В общем, рекомендация: сначала думать, и только потом писать на форум.

И еще.

Если хотите помощи, следует опубликовать скетч, над которым работаете. Нет скетча - автоматически будете посланы в "Ищу исполнителя". Считайте это правилами форума. (Кстати, прежде, чем писать на любой форум, его рекомендуется почитать. Увы, Вы этого не сделали.)

IAlexandrN
Offline
Зарегистрирован: 27.11.2017

Что я вкладываю в понятие "тестирование релейной платы" (РП):

1. подключение РП к тестеру

2. подача питания на тестер (5 В)

3. запуск теста с тактовой кнопки

4. по питанию 5 В: измерение I потр.общ., сравнение с эталоном, выявление аномалий - КЗ, отсутствие/увеличенное потребление тока.

5. по питанию 24 В: измерение I потр.общ. при отключенных реле, сравнение с эталоном, выявление аномалий - КЗ, отсутствие/увеличенное потребление тока

6. одновременное включение всех реле, измерение I потр.общ. и сравнения с эталоном. Выявление аномалий - КЗ, отсутствие потребления тока по питанию 24 В.

7. поочередное включение каждого реле, измерение потребялемого тока включенного реле, сравнение с эталоном. 

8. поочередное включение каждого реле (линии) и проверку прохождения сигналов с входов на выходы, выявление обрывов и/или дублирования на других линиях.

9. проверка наличия сигнала на физическом выводе с РП с выхода Q7S второго регистра 74НС594, расположенного на РП.

10. автоостановка теста по окончанию.

11. вывод промежуточных и общего результатов на LCD дисплей, в монитор порта (последнее, если модуль arduino подключен к ПК).

12. отключение питания от тестера 

13. отключение РП от тестера 

IAlexandrN
Offline
Зарегистрирован: 27.11.2017

То, что уже написал:

/* Тестер релейной платы (РП) 3 входа 6 выходов. Программно-аппаратное средство для проверки корректности прохождения сигналов по линиям от входов к выходу.
 * Имеет встроенный I2C дисплей, датчик тока (на MAX471 или ACS712 ?), повышающий  преобразователь напряжения 5 В => 24 В (на MC33063) с защитой по току для питания реле.
 * Принцип работы: с микроконтроллера Arduino Uno (nano) на 2 сдвиговых регистра 74HC594 релейной платы подается управлявлящий сигнал для переключения реле.
 * к Q7S выходу второго регистра, присутсвующему на РП, подключены два внешних сдвиговых регистра 74HC594, которые формируют логический сигнал для подачи его 
 * на ВЫХОДЫ(!) линий РП. Это позволяет: 1) проверить наличие коррректного сигнала на выходе Q7S РП: 2)подавая сформированный на доп. регистрах сигнал,  
 * проверять наличие и правильность прохождения сигнала от ВЫХОДОВ(!) РП до ВХОДОВ(!) РП. Этот сигнал снимается со ВХОДОВ(1) РП двумя цифровыми входами МК, сравнивается с эталонным,
 * после чего выводится результат теста каждой линии и общий. (После чего тест должен останавливаться, и рестартовать по нажатию кнопки)
*/
#include <LiquidCrystal_I2C.h>                      // для работы с LCD дисплеем подключаем библиотеку LiquidCrystal_I2C.h
#include <Wire.h>                                   // для работы с шиной I2C подключаем библиотеку Wire.h

LiquidCrystal_I2C lcd(0x20,16,2);                   // Указываем адрес и тип дисплея

int dataPin  = 9;                                   // пин arduino uno 9 подключен к 14 DS входу 74HC594 (вход релейной платы 11)
int latchPin = 10;                                  // пин arduino uno 10 подключен к 12 ST_CP входу 74HC594 (вход релейной платы 7)
int clockPin = 11;                                  // пин arduino uno 11 подключен к 11 SH_CP входу 74HC594 (вход релейной платы 9)
int input1 = 6;                                     // пин arduino uno для считывания состояния с "+ Вход 1"
int input2 = 7;                                     // пин arduino uno для считывания состояния с "- Вход 1"
const int chtenie = 500;                            // задаем константу для задержки после чтения состояния реле
const int ustanovka = 500;                          // задаем константу для задержки после установки реле в нужное состояние
boolean p;                                          // объявляем переменную p (positive) для отображения прохождения сигнала по плюсовой дорожке
boolean n;                                          // объявляем переменную n (negative) для отображения прохождения сигнала по минусовой дорожке
boolean result;                                     // объявляем переменную result для отображения корректности прохождения сигнала по дорожкам



void setup()
{
  Serial.begin(9600);
  pinMode(latchPin, OUTPUT);                        // указываем режимы работы выводов
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
  pinMode(input1, INPUT);
  pinMode(input2, INPUT);
  lcd.init();                                       // инициализация дисплея
  lcd.backlight();                                  // включить подсветку дисплея
  lcd.clear();                                      // очистить дисплей
  lcd.setCursor(0, 0);                              // установить курсор в начало 1-й строки
  lcd.print("______test_______");                   // вывести на дисплей '______test_______'
  delay(50);
  lcd.setCursor(3, 1);                              // установить курсор на 4-й символ 2-й строки
  lcd.print("Commutator");                          // вывести на диспле 'Commutator'
  delay(500);
  lcd.clear();                                      // очистить дисплей  
  myf(B00000000, B00000000, B00000000, B00000000);  // установить реле в начальное положение


}

void loop()
{
  // начало теста. проверка прохождения сигнала с 6-ти входов на 1-й выход
  boolean relay_1 = 0;                              // объявляем флаг корректности работы для Реле 1
  boolean relay_2 = 0;                              // объявляем флаг корректности работы для Реле 2
  boolean relay_3 = 0;                              // объявляем флаг корректности работы для Реле 3
  boolean relay_4 = 0;                              // объявляем флаг корректности работы для Реле 4
  boolean relay_5 = 0;                              // объявляем флаг корректности работы для Реле 5
  boolean relay_6 = 0;                              // объявляем флаг корректности работы для Реле 6

  lcd.setCursor(0, 0);                              // установить курсор в начало 1-й строки
  lcd.print("OUT");                                 // вывести на дисплей 'OUT'
  delay(50);
  lcd.setCursor(0, 1);                              // установить курсор на 1-й символ 2-й строки
  lcd.print("IN1");                                 // вывести на дисплей 'IN1'
  Serial.println("Outputs to Input 1");

// РЕЛЕ 1  
  myf(B00000000, B00000001, B01000000, B00000001);  // для 1-го реле подключить 1-й вход к 1-му выходу 1 и подать на + контакт 1-го выхода лог единицу.
    p = myf_read_p(HIGH, LOW);                      // проверка прохождения сигнала через + конт. 
    sp_p(1, p);                                     // вывод промежуточного результата по + контакту в монитор порта
 
  myf(B00000000, B00000010, B01000000, B00000001);  // для 1-го реле подключить 1-й вход к 1-му выходу 1 и подать на - контакт 1-го выхода лог единицу.
    n = myf_read_n(LOW, HIGH);                      // проверка прохождения сигнала через - конт, указание состоний которые должны быть на считывающих входах при корректном прохождении синала
    sp_n(1, n);                                     // вывод промежуточного результата по - контакту в монитор порта
  
    if(p == true && n == true){                     // если сигналы от выхода до входа по обоим дорожкам прошли штатно
      print_lcd_v(1);                               // выводим на LCD номер реле и галочку под ним
      relay_1 = 1;                                  // устанавливаем флаг символизирующий корректный тест 1-го реле 
    }
    else{                                           // если возникла ошибка
      print_lcd_X(1);                               // выводим на LCD номер реле и крестик под ним
    }

// РЕЛЕ 2
  myf(B00000000, B00000100, B01000000, B00000100);  // для 2-го реле подключить 1-й вход к 1-му выходу 1 и подать на + контакт 1-го выхода лог единицу.
    p = myf_read_p(HIGH, LOW);                      // проверка прохождения сигнала через + конт, указание состоний которые должны быть на считывающих входах при корректном прохождении синала 
    sp_p(2, p);                                     // вывод промежуточного результата по + контакту в монитор порта
 
  myf(B00000000, B00001000, B01000000, B00000100);  // для 2-го реле подключить 1-й вход к 1-му выходу 1 и подать на - контакт 1-го выхода лог единицу.
    n = myf_read_n(LOW, HIGH);                      // проверка прохождения сигнала через - конт, указание состоний которые должны быть на считывающих входах при корректном прохождении синала
    sp_n(2, n);                                     // вывод промежуточного результата по - контакту в монитор порта
  
    if(p == true && n == true){                     // если сигналы от выхода до входа по обоим дорожкам прошли штатно
      print_lcd_v(2);                               // выводим на LCD номер реле и галочку под ним
      relay_2 = 1;                                  // устанавливаем флаг символизирующий корректный тест 2-го реле 
    }
    else{                                           // если возникла ошибка
      print_lcd_X(2);                               // выводим на LCD номер реле и крестик под ним
    }

// РЕЛЕ 3
  myf(B00000000, B00010000, B01000000, B00010000);  // для 3-го реле подключить 1-й вход к 1-му выходу 1 и подать на + контакт 1-го выхода лог единицу.
    p = myf_read_p(HIGH, LOW);                      // проверка прохождения сигнала через + конт, указание состоний которые должны быть на считывающих входах при корректном прохождении синала
    sp_p(3, p);                                     // вывод промежуточного результата по + контакту в монитор порта
 
  myf(B00000000, B00100000, B01000000, B00010000);  // для 3-го реле подключить 1-й вход к 1-му выходу 1 и подать на - контакт 1-го выхода лог единицу.
    n = myf_read_n(LOW, HIGH);                      // проверка прохождения сигнала через - конт, указание состоний которые должны быть на считывающих входах при корректном прохождении синала
    sp_n(3, n);                                     // вывод промежуточного результата по - контакту в монитор порта
  
    if(p == true && n == true){                     // если сигналы от выхода до входа по обоим дорожкам прошли штатно
      print_lcd_v(3);                               // выводим на LCD номер реле и галочку под ним
      relay_3 = 1;                                  // устанавливаем флаг символизирующий корректный тест 3-го реле 
    }
    else{                                           // если возникла ошибка
      print_lcd_X(3);                               // выводим на LCD номер реле и крестик под ним
    }

// РЕЛЕ 4
  myf(B00000000, B01000000, B01000000, B01000000);  // для 4-го реле подключить 1-й вход к 1-му выходу 1 и подать на + контакт 1-го выхода лог единицу.
    p = myf_read_p(HIGH, LOW);                      // проверка прохождения сигнала через + конт, указание состоний которые должны быть на считывающих входах при корректном прохождении синала 
    sp_p(4, p);                                     // вывод промежуточного результата по + контакту в монитор порта
 
  myf(B00000000, B10000000, B01000000, B01000000);  // для 4-го реле подключить 1-й вход к 1-му выходу 1 и подать на - контакт 1-го выхода лог единицу.
    n = myf_read_n(LOW, HIGH);                      // проверка прохождения сигнала через - конт, указание состоний которые должны быть на считывающих входах при корректном прохождении синала
    sp_n(4, n);                                     // вывод промежуточного результата по - контакту в монитор порта
  
    if(p == true && n == true){                     // если сигналы от выхода до входа по обоим дорожкам прошли штатно
      print_lcd_v(4);                               // выводим на LCD номер реле и галочку под ним
      relay_4 = 1;                                  // устанавливаем флаг символизирующий корректный тест 4-го реле 
    }
    else{                                           // если возникла ошибка
      print_lcd_X(4);                               // выводим на LCD номер реле и крестик под ним
    }

// РЕЛЕ 5
  myf(B00000001, B00000000, B01000001, B00000000);  // для 5-го реле подключить 1-й вход к 1-му выходу 1 и подать на + контакт 1-го выхода лог единицу.
    p = myf_read_p(HIGH, LOW);                      // проверка прохождения сигнала через + конт, указание состоний которые должны быть на считывающих входах при корректном прохождении синала
    sp_p(5, p);                                     // вывод промежуточного результата по + контакту в монитор порта
 
  myf(B00000010, B00000000, B01000001, B00000000);  // для 5-го реле подключить 1-й вход к 1-му выходу 1 и подать на - контакт 1-го выхода лог единицу.
    n = myf_read_n(LOW, HIGH);                      // проверка прохождения сигнала через - конт, указание состоний которые должны быть на считывающих входах при корректном прохождении синала
    sp_n(5, n);                                     // вывод промежуточного результата по - контакту в монитор порта
    if(p == true && n == true){                     // если сигналы от выхода до входа по обоим дорожкам прошли штатно
      print_lcd_v(5);                               // выводим на LCD номер реле и галочку под ним
      relay_5 = 1;                                  // устанавливаем флаг символизирующий корректный тест 5-го реле 
    }
    else{                                           // если возникла ошибка
      print_lcd_X(5);                               // выводим на LCD номер реле и крестик под ним
    }

// РЕЛЕ 6
  myf(B00000100, B00000001, B01000100, B00000000);  // для 6-го реле подключить 1-й вход к 1-му выходу 1 и подать на + контакт 1-го выхода лог единицу.
    p = myf_read_p(HIGH, LOW);                      // проверка прохождения сигнала через + конт, указание состоний которые должны быть на считывающих входах при корректном прохождении синала  
    sp_p(6, p);                                     // вывод промежуточного результата по + контакту в монитор порта
 
  myf(B00001000, B00000010, B01000100, B00000000);  // для 6-го реле подключить 1-й вход к 1-му выходу 1 и подать на - контакт 1-го выхода лог единицу.
    n = myf_read_n(LOW, HIGH);                      // проверка прохождения сигнала через - конт, указание состоний которые должны быть на считывающих входах при корректном прохождении синала
    sp_n(6, n);                                     // вывод промежуточного результата по - контакту в монитор порта
    if(p == true && n == true){                     // если сигналы от выхода до входа по обоим дорожкам прошли штатно
      print_lcd_v(6);                               // выводим на LCD номер реле и галочку под ним
      relay_6 = 1;                                  // устанавливаем флаг символизирующий корректный тест 6-го реле 
    }
    else{                                           // если возникла ошибка
      print_lcd_X(6);                               // выводим на LCD номер реле и крестик под ним
    }


  
  if(relay_1 == relay_2 == relay_3 == relay_4 == relay_5 == relay_6 == 1){   //если тесты всех реле удачны и равны 1
    Serial.println("Test passed");                  // в монитор порта вывести Test passed
    lcd.setCursor(12, 0);                           // на дисплей в две строки вывести 'TEST PASS'
    lcd.print("TEST");
    lcd.setCursor(12, 1);
    lcd.print("PASS");
    delay(500); 
  }
  else{
    Serial.println("Test fail");                    // в монитор порта вывести Test fail
    lcd.setCursor(12, 0);                           // на дисплей в две строки вывести 'TEST FAIL'
    lcd.print("TEST");
    lcd.setCursor(12, 1);
    lcd.print("FAIL");
    delay(500); 
  }
}
/*Первые два регистра 74HC594 служат для управления релейной платой и установлены на ней же 
 * вторые два регистра устанавливаются на плате тестера и служат для: 
 * 1) проверки выхода Q7S последнего регистра с релейной платы
 * 2) для формирования сигналов, подаваемых на выходы каналов коммутации.
*/
void myf(int adress1, int adress2, int adress3, int adress4){ //функция принимает адреса и, соответственно им, устанавливает сдвиговые регистры
  digitalWrite(latchPin, LOW);                      // установить синхронизацию "защелки" на LOW
  shiftOut(dataPin, clockPin, MSBFIRST, adress1);   // в первый регистр отправить слева направо байт для 4-го регистра
  shiftOut(dataPin, clockPin, MSBFIRST, adress2);   // в первый регистр отправить слева направо байт для 3-го регистра, продвинуть далее байт для 4-го
  shiftOut(dataPin, clockPin, MSBFIRST, adress3);   // в первый регистр отправить слева направо байт для 2-го регистра, продвинуть далее байт для 4-го и 3-го
  shiftOut(dataPin, clockPin, MSBFIRST, adress4);   // в первый регистр отправить слева направо байт для 1-го регистра, продвинуть далее байт для 4-го, 3-го и 2-го
  digitalWrite(latchPin, HIGH);                     // установить синхронизацию "защелки" на HIGH
  delay(ustanovka);                                 // задержка перед чтением
}  

boolean myf_read_p(int a, int b){                   // для плюсового проводника функция принимает состояния корректности для выводов 6 и 7 и сравнивает со считанными состояниями. Возвращает логический результат сравнения.
  if (digitalRead(6) == a  && digitalRead(7) == b){ // если считанные состояния равны входным аргументам
    result = true;                                  // то сигнал проходит по + контакту линии корректно, результат присвает значение истинности
  }
  else{                                             // если считанные состояния ошибочны или отсутствуют
    result = false;                                 // то сигнал не проходит по + контакту линии, дублируется по - или идёт только по -, результат присвает значение ложь
  }
  return result;                                    // функция возвращает вместо себя результат проверки
  delay(chtenie);                                   // задержка перед установкой реле в следующее состояние
}

boolean myf_read_n(int a, int b){                   // для минусового проводника функция принимает аргументы корректности для выводов 6 и 7 и сравнивает со считанными состояниями. Возвращает логический результат сравнения.
  if (digitalRead(6) == a  && digitalRead(7) == b){ // если считанные состояния равны входным аргументам 
    result = true;                                  // то сигнал проходит по - контакту линии корректно, результат присвает значение истинности
  }
  else{                                             // если считанные состояния ошибочны или отсутствуют
    result = false;                                 // то сигнал не проходит по - контакту линии, дублируется по + или идёт только по +, результат присвает значение ложь
  }
  return result;                                    // функция возвращает вместо себя результат проверки
  delay(chtenie);                                   // задержка перед установкой реле в следующее состояние
}

void sp_p(int num_relay, boolean p){                // вывод в монитор порта состояния по + контакту
  if(p == true){                                    // если сигнал прошел с плюса выхода на плюс входа и только по + контакту
    Serial.print("Relay ");                         // вывести в монитор порта Relay 'номер линии' + ok 
    Serial.print(num_relay);
    Serial.println(" + ok");
  }
  else{                                             // если сигнал с плюса выхода не прошел на плюс входа или задублировался по - контакту
    Serial.print("Relay ");                         // вывести в монитор порта Relay 'номер линии' + break
    Serial.print(num_relay);
    Serial.println(" + break");
  }
}

void sp_n(int num_relay, boolean n){                // вывод в монитор порта состояния по - контакту
  if(n == true){                                    // если сигнал прошел с минуса выхода на минус входа и только по - контакту
    Serial.print("Relay ");                         // вывести в монитор порта Relay 'номер линии' - ok 
    Serial.print(num_relay);
    Serial.println(" - ok");
  }
  else{                                             // если сигнал с минуса выхода не прошел на минус входа или задублировался по + контакту
    Serial.print("Relay ");                         // вывести в монитор порта Relay 'номер линии' - break
    Serial.print(num_relay);
    Serial.println(" - break");
  }
}

// функция принимает аргумент 'номер линии', выводит на дисплей номер линии и, под ним, результат проверки: 'v' - успешно, 'X' - ошибка
void print_lcd_v(int line){              
    lcd.setCursor(line+3, 0);
    lcd.print(line);
    lcd.setCursor(line+3, 1);
    lcd.print("v");
    delay(50);
}

// функция принимает аргумент 'номер линии', выводит на дисплей номер линии и, под ним, результат проверки: 'v' - успешно, 'X' - ошибка
void print_lcd_X(int line){
    lcd.setCursor(line+3, 0);
    lcd.print(line);
    lcd.setCursor(line+3, 1);
    lcd.print("X");
    delay(50);
}

Проверял в Proteus - работает.

Есть проект в Proteus, если надо могу выложить.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Первое что надо сделать это загнать все  74HC595 в класс и написать для них write(/*номер микросхемы*/,/*номер вывода*/);

IAlexandrN
Offline
Зарегистрирован: 27.11.2017

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

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Теже  яйца, только в профиль. В классе создать два метода (write и writeByte). один для побитного изменения, а второй для побайтного.

arduino328
Offline
Зарегистрирован: 01.09.2016

IAlexandrN пишет:

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

qwone помешан на классах, но программировать можно и без них. Если получается рабочий код без классов, то делайте как вам удобно.

IAlexandrN
Offline
Зарегистрирован: 27.11.2017

С датчиками тока пока ничего не вышло. ACS712 больше подойдут для высоких токов (единицы, десятки А) и то скорее для индикации. MAX471 не заработали. При подаче питания 5 В греются до 70 град. При нагрузке 500 мА - кипяток.

IAlexandrN
Offline
Зарегистрирован: 27.11.2017

qwone, найдется минутка для помочь по классам касаемо 74HC594?

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

???

IAlexandrN
Offline
Зарегистрирован: 27.11.2017

Для уверенности, что включено только одно реле и скоммутирована только одна нужная линия, нужно пройтись логической единицей по всем выходам. На кажый выход (из 6) подается лог единица и снимается с требуемого входа. Вход должен быть проинформирован в каком случае на нем может быть лог ед. Т.е. сконфигурировали сдвиговые регистры так, что замыкается вход 2 с выходом 5, подали на выход 5 лог.ед. а вход 2 предупредили что сейчас он должен принять высокий уровень. Если ок, то ок, но ведь в этот момент в случае неисправности на плате могут включиться и другие реле. Убираем лог.ед. с выхода 5 и поочереди подаем на другие выходы. Вход 2 должен понимать, что в этих случаях он должен видеть только низкий уровень, иначе ахтунг! Как осуществить такой перебор?

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

А чем вам такой принцип не подходит? https://lesson.iarduino.ru/page/urok-13-podklyuchenie-klaviatury-4-4-i-pezoizluchatelya-k-arduino/

IAlexandrN
Offline
Зарегистрирован: 27.11.2017

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

IAlexandrN
Offline
Зарегистрирован: 27.11.2017

есть 4 шт 74hc594. 2 управляют реле, 2 формирут тестовые сигналы.  биты на формирователи идут через через селекторов. Все 4 штуки подключены каскадно одна за другой. Правильно ли будет создать 2 класса "селектор" и "формирователь сигналов" ?

// класс селектор входов
class selektor IN_OUT {
  private:
  public:
}

// класс формирователь сигналов
class form{
  private:
  public: 
}
qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Для написания кода надо пройти 4(четыре!!)этапа . 1 -Составление ТЗ,2-проектирование программы-3написание кода 4заливка и отладка. Я всегда это говорю. Но для вашего случая надо написать внятное ТЗ. И ТЗ не только о железе, но и работой пользователя с этим железом. Что еще важнее. Если у вас случай. Когда к примеру есть 4 гнезда в которые суются тестируемые реле. Разумнее конечно по одному - Воткнул высунул и в результате Годно Не годно. Но похоже вам такой вариант не подходит. де Сад рулит не только в сексе, но и в "трахе на работе". Так что начинайте писать мануал для пользователя вашего девайса. А без этого вы застрянете на 4 этапе и будете "искать ключи под фонарем, потому что там светлее, а не потому что вы там их потеряли". 

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Не верно. 1 класс это шина на которой висят 74hc594. А вот дальше создаете класс реле и формирователей которые висят на этой шине.

IAlexandrN
Offline
Зарегистрирован: 27.11.2017

Есть релейные платы с гнездами (входами и выходами). Пользователь (тестировщик) берет плату, подключает кабелями к коробочке, подает питание на коробочку и нажимает кнопку старта тестирования. Коробочка шурует релюшками на плате. Подает сигналы куда надо, считывает сигналы. Потом выдает "Test PASS" или "Test FAIL". Далее текстировщиком отключаются питание, кабели,  плата по результату откладывается налево или направо. Если получится, то одна коробочка будет тестировать 2 разных платы - красненькую (3 Входа 6 выходов)  и синенькую (2 входа 4 выхода ). Тогда кнопок на коробочке должно быть две - для красной и для синей плат. Алгоритм тестирования тот же. 

 

IAlexandrN
Offline
Зарегистрирован: 27.11.2017

qwone, про класс шины (SPI) на пальцах можно объяснить, показать как это должно выглядеть?

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Ну для эскиза примерно так 

/**/
unsigned long mill; // переменная под millis()
//--------------------------------
class Cl_Bus {
  protected:
    byte p1, p2, p3;/*пины*/
    byte n;/*колличество в шине*/
    byte buffer[4];
  public:
    /*конструктор*/
    Cl_Bus(byte p1_, byte p2_, byte p3_, byte n)
      : p1(p1_), p2(p2_), p3(p3_) {}
    /*инициализация-вставить в setup()*/
    void init() {

    }
    /*отправка*/
    void tranfer(byte a, byte b) {
    }
};
class Cl_Relay {
  protected:
    Cl_Bus *Bus;
    byte addr, bit_;
  public:
    /**/
    Cl_Relay(Cl_Bus *B, byte a, byte b): Bus(B), addr(a), bit_(b) {}
    /*инициализация-вставить в setup()*/
    void init() {
    }
};
//---Компоновка-----------------------------
Cl_Bus Bus(/*пин*/2,/*пин*/4,/*пин*/5,/*кол-во*/4);
Cl_Relay Relay1 (/*шина*/&Bus,/*поз*/0,/*бит*/2);
Cl_Relay Relay2 (/*шина*/&Bus,/*поз*/0,/*бит*/3);
//---main-----------------------------
void setup() {
  Bus.init();
  Relay1.init();
  Relay2.init();
}


void loop() {
  mill = millis();
}
/*Скетч использует 578 байт (1%) памяти устройства. Всего доступно 30720 байт.
  Глобальные переменные используют 29 байт (1%) динамической памяти, оставляя 2019 байт для локальных переменных. Максимум: 2048 байт.
*/

 

IAlexandrN
Offline
Зарегистрирован: 27.11.2017

Жесть. Спасибо. Сейчас я буду это переваривать. Как же мне нравится мой лосиный код, ведья я его понимаю :(

IAlexandrN
Offline
Зарегистрирован: 27.11.2017

qwone, с вами можно как-то связаться через ЛС?

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Код примитивен как доска. Это просто остальных приучили бесперспективному стилю. Вот нород и шарахается. Вы поробуйте это нарисовать на своем коде #220   А ведь это банально просто подключающий компонент.

IAlexandrN
Offline
Зарегистрирован: 27.11.2017

Возможно ли более кратко записать условие вида

 if(relay1_1 == relay2_1 && relay2_1 == relay3_1 && relay3_1 == relay4_1 && relay4_1 == relay5_1 && relay5_1 == relay6_1 && relay6_1 == relay1_2 && relay1_2 == relay2_2 && relay2_2 == relay3_2 && relay3_2 == relay4_2 && relay4_2 == relay5_2 && relay5_2 == relay6_2 && relay6_2 == 1){ 

Это флаги указывающие корректность промежуточных операций. Если все флаги равны единице (сответсвенно равны между собой), то тест корректен.

sadman41
Offline
Зарегистрирован: 19.10.2016

Насчет короче - не уверен, но красивее можно. При условии, что эти величины будут в массиве и все будут , например, ненулевые.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Похоже вы так и не поняли цель проекта.Возьмем красненькую плату (3 Входа 6 выходов) . 3 входа - всего 8 состояний. Это банально перебрать и сравнить что получилось на выходе. Логический элемент. Но так как у вас это 3 реле , а у реле контактная пара. Пусть один конец это будет еще один вход. И в результате перебор  3 входа+3 входа(контактных) на 3 выхода контактых. 64 варианта на 3битное состояние (000,001...111) . Если где-то ошибка, то негодно.  Тоже и с синенькой.

6 выходов это 1 74hc594(3 пина Ардуины)+3 входа(тоже 3 пина Ардуины)

Шины не надо. 

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

IAlexandrN пишет:

Возможно ли более кратко записать условие вида

 if(relay1_1 == relay2_1 && relay2_1 == relay3_1 && relay3_1 == relay4_1 && relay4_1 == relay5_1 && relay5_1 == relay6_1 && relay6_1 == relay1_2 && relay1_2 == relay2_2 && relay2_2 == relay3_2 && relay3_2 == relay4_2 && relay4_2 == relay5_2 && relay5_2 == relay6_2 && relay6_2 == 1){ 

Это флаги указывающие корректность промежуточных операций. Если все флаги равны единице (сответсвенно равны между собой), то тест корректен.

Если это булевые переменные, то:

if(relay1_1 & relay2_1 & relay3_1 & relay4_1 & relay5_1 & relay6_1 & relay1_2 & relay2_2 & relay3_2 & relay4_2 & relay5_2 & relay6_2){ 

 

IAlexandrN
Offline
Зарегистрирован: 27.11.2017

Действительно я мало что понял по классам. На плате 2 сдвиговых регистра 74НС594 включены каскадом. Более того, выход Q7S (serial data output) второй микросхемы идет на краевой разъем, для возможности каскадного соединения релейных плат для увеличения общего кол-ва выходов. Стало быть шина здесь очень нужна - по ней все управление, + по ТЗ требуется проверка наличия сигнала на краевом разъеме платы с выхода Q7S. В том числе и для этого я приляпал еще внешние 2 шт 74HC594, включенных последовательно с предыдущими двумя.

IAlexandrN
Offline
Зарегистрирован: 27.11.2017

andriano, да, переменные boolean. Понял. Это "побитовое И" или "амперсанд (&)" в С++. Только если все члены выражения равны единице, тогда результат тоже будет единица. Спасибо.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

IAlexandrN пишет:

Только если все члены выражения равны единице, тогда результат тоже будет единица.

А Вам разве не это нужно?

IAlexandrN
Offline
Зарегистрирован: 27.11.2017

Именно это.