Ви не увійшли.
Потрібна допомога в редагуванні скетчу, оскільки для мене тема з ардуіно нова,не можу сам впоратися тому прошу про допомогу
Суть проблеми,є 4 канальний модуль реле часу на базі ардуінки про міні,і є готовий скетч під це діло,але проблема заключається в тому що при подачі сигналу реле часу працює циклічно,тобто реле умовно відпрацювало 5 секунд а сигнал поступає нерозривно більше 5 секунд і реле часу спрацьовує знову а потрібно щоб незалежно від часу на який подається сигнал реле відпрацювало умовно 5 секунд і відключилось до моменту поки не буде наступного сигналу, якщо хтось зможе допогти буду дуже вдячний
Прикріпив архів з усіма даними по модулю
IO22C04-4-Channel-Pro-mini-PLC-Board.rarIO22C04-4-Channel-Pro-mini-PLC-Board.rar
Неактивний
Дивитись код всередині архіву неспортивно Акби воно на гітхабі було, з синтаксисом..
Спробую вгадати.
Ви в циклі міряєте логічний рівень на якомусь піні. Якщо там 1 - запускаєте якийсь процес довжиною 5 сек. Коли процес закінчується - там знову все ще 1.
Рішення таке: треба порвінювати рівень який зараз з попереднім рівнем; якщо вони відрізняються, тоді щось робити.
Неактивний
uint_8t prev_value;
void setup()
{
prev_value = digitalRead(somePin);
}
void loop()
{
uint8_t new_value = digitalRead(somePin);
if (new_value != prev_value)
{
prev_value = new_value;
do_some_shit();
}
}
Десь так.
Якщо треба щоб воно реагувало не на будь яку зміну сигналу, а лише на ввімкнення - добавте ще один if, я впевнений, все вийде
Якщо треба вміти ловити сигнал під час роботи 5 секундної функції, значить треба робити інакше. На перериваннях, наприклад.
Неактивний
є готовий скетч під це діло
В тому скетчі одразу впадає в очі як мінімум один баг: TubeDisplay4Bit() виконується в контексі переривання і читає та пише int relay*_time_left. В loop() ці змінні також модифікуються без будь-якої синхронізації.
Також uchar OneSecondCnt як глобальна змінна ініціалізована нулем, потім
OneSecondCnt--;
if(OneSecondCnt==0) ...
Тобто переходить через переповнення - навряд чи так було спеціально задумано.
Ще купа інших недоліків у тому коді, але про них поки промовчу.
але проблема заключається в тому що при подачі сигналу реле часу працює циклічно,тобто реле умовно відпрацювало 5 секунд а сигнал поступає нерозривно більше 5 секунд і реле часу спрацьовує знову а потрібно щоб незалежно від часу на який подається сигнал реле відпрацювало умовно 5 секунд і відключилось до моменту поки не буде наступного сигналу
Так у вас умова вмикання реле - це низький рівень на вході:
if (digitalRead(INPUT1)==LOW) { ... digitalWrite(j1, HIGH);digitalWrite(led, HIGH); } ...
А умова вимикання - закінчення відліку лічильника
if (relay1_time_left>0) { ... } else { digitalWrite(j1, LOW); relay1_display = relay1_delay_time;}
Як сказано у коментарі вище, потрібно перемикати стан не по значенню рівня на вході, а по факту зміни цього рівня.
Але мені здається, набагато легше буде написати нормально з нуля, чим виправляти той "готовий" гів код.
Остання редакція dimich (2025-02-24 16:06:48)
Неактивний
Взагалі бажано спочатку намалювати на папірці якісь графіки-квадратики-стрілки, а вже потім хапатись кодити. Бо по перше у вас вийде код, який складно читати. По друге, вам буде складно вносити туди зміни.
Неактивний
Так у вас умова вмикання реле - це низький рівень на вході:
if (digitalRead(INPUT1)==LOW) { ... digitalWrite(j1, HIGH);digitalWrite(led, HIGH); } ...
А умова вимикання - закінчення відліку лічильника
if (relay1_time_left>0) { ... } else { digitalWrite(j1, LOW); relay1_display = relay1_delay_time;}
так і задумано щоб реле вмикалось при подачі низького рівня від датчика але потрібно щоб незележно від того наскільки довго подається сигнал з датчика реле відпрацювало і вмикалось далі до того часу поки не буде наступного сигналу,тому що зараз якщо сигнал з датчика перевищує час відпрацювання реле то реле включається повторно
Неактивний
Як сказано у коментарі вище, потрібно перемикати стан не по значенню рівня на вході, а по факту зміни цього рівня.
Але мені здається, набагато легше буде написати нормально з нуля, чим виправляти той "готовий" гів код.
Нажаль я в тому новачок тому для мене то і є проблема,якщо ви зможете написати новий код за адекватну винагороду тоді я тільки за
Неактивний
if (digitalRead(INPUT1)==LOW)
uint8_t new_value = digitalRead(somePin);
if (new_value != prev_value)
{
prev_value = new_value;
do_some_shit()uint8_t new_value = digitalRead(somePin);
if (new_value != prev_value)
{
prev_value = new_value;
if (new_value == LOW)
need_start = true;
};
}
if (need_start) {need_start = false;...}
Неактивний
Ну я в же один раз пропонував використовувати не низький рівень, а перехід з високого рівня в низький.
але питання як це організувати,я не можу подати високий рівень у вигляді сигналу,оскільки там не 5в і ардуінка не переварить а щось кардинально міняти по технічці не хотілося б
Неактивний
так і задумано щоб реле вмикалось при подачі низького рівня від датчика але потрібно щоб незележно від того наскільки довго подається сигнал з датчика реле відпрацювало і вмикалось далі до того часу поки не буде наступного сигналу,тому що зараз якщо сигнал з датчика перевищує час відпрацювання реле то реле включається повторно
У вас є вхід з двома станами: низький / високий рівень (можливий брязкіт контактів поки до уваги не берем).
Є вихід з двома станами: реле вимкнене / увімкнене.
Є внутрішній стан таймера: активний / неактивний.
Це вже дає 8 можливих комбінацій (частина з них потім редукується). Для початку намалюйте діаграму або таблицю переходів. Для кожного переходу визначте умову (стан входу, стан таймера), а також дії, які мають виконатись (увімкнути/вимкнути реле, запустити таймер і т.п.).
Поки реле увімкнене, повторний перехід з високого на низький рівень на вході має перезапускати таймер? Чи стан вхіду має значення тільки після вимкнення реле?
Неактивний
ну я ж код написав..
пробував попередній варіан в різних варіаціях нічого не виходить,якщо не важко напишіть на коді один приклад конкретний
/*---Segment Display Screen----
--A--
F---B
--G--
E---C
--D--
__ __ __ __
|__||__|.|__||__|
|__||__|'|__||__|
----------------------*/
#include "FlexiTimer2.h"
#define uchar unsigned char
#define uint unsigned int
int display_dat;
int key_value;
const int led = 13;
//Pin connected to latch of Digital Tube Module
const int latch = 8;
//Pin connected to click of Digital Tube Module
const int clock = 9;
//Pin connected to data of Digital Tube Module
const int data = 7;
const int K1 = 2;
const int K2 = 3;
const int K3 = 4;
const int K4 = 5;
const int INPUT1 = A1;
const int INPUT2 = A0;
const int INPUT3 = A3;
const int INPUT4 = A2;
const int j1 = 10;
const int j2 = 11;
const int j3 = 12;
const int j4 = 6;
int relay1_delay_time = 5;//1-9999 seconds,Modify the number change the delay time
int relay2_delay_time = 5;//1-9999 seconds,Modify the number change the delay time
int relay3_delay_time = 5;//1-9999 seconds,Modify the number change the delay time
int relay4_delay_time = 5;//1-9999 seconds,Modify the number change the delay time
int relay1_time_left;
int relay2_time_left;
int relay3_time_left;
int relay4_time_left;
int relay1_display;
int relay2_display;
int relay3_display;
int relay4_display;
/* NO.:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22 23 24 25 26 27 28
/*Character :0,1,2,3,4,5,6,7,8,9,A, b, C, c, d, E, F, H, h, L, n, N, o, P, r, t, U, -, ,*/
uchar TUBE_SEG[] =
{0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa7,0xa1,0x86,0x8e,0x89,0x8b,0xc7,0xab,0xc8,0xa3,0x8c,0xaf,0x87,0xc1,0xbf,0xff};//Common anode Digital Tube Character Gallery
uchar TUBE_NUM[8]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//Tuble bit number
uchar dat_buf[8];
//***********************************************
// dat : Data to be displayed
// com_num : Digital Tube Common
//***********************************************
uchar dat;
uchar com_num;
void TubeDisplayOneBit()
{
uchar tube_dat;
uchar bit_num;
tube_dat = TUBE_SEG[dat]; //Common Cathode Digital Tube,bit negated
bit_num = ~TUBE_NUM[com_num];
//ground latchPin and hold low for as long as you are transmitting
digitalWrite(latch, LOW);
shiftOut(data, clock, MSBFIRST, bit_num);
shiftOut(data, clock, MSBFIRST, tube_dat);
//return the latch pin high to signal chip that it
//no longer needs to listen for information
digitalWrite(latch, HIGH);
}
uchar OneSecondCnt;
void TubeDisplay4Bit(void)
{
if(com_num<3) com_num ++;else com_num=0;
dat = dat_buf[com_num];
TubeDisplayOneBit();
OneSecondCnt--;
if(OneSecondCnt==0)
{
OneSecondCnt = 1000;
if(relay1_time_left>0){relay1_time_left--; relay1_display = relay1_time_left;} else {digitalWrite(j1, LOW);relay1_display = relay1_delay_time;}
if(relay2_time_left>0){relay2_time_left--; relay2_display = relay2_time_left;} else {digitalWrite(j2, LOW);relay2_display = relay2_delay_time;}
if(relay3_time_left>0){relay3_time_left--; relay3_display = relay3_time_left;} else {digitalWrite(j3, LOW);relay3_display = relay3_delay_time;}
if(relay4_time_left>0){relay4_time_left--; relay4_display = relay4_time_left;} else {digitalWrite(j4, LOW);relay4_display = relay4_delay_time;}
}
if(key_value==0) display_dat = relay1_display;
else if(key_value==1) display_dat = relay2_display;
else if(key_value==2) display_dat = relay3_display;
else display_dat = relay4_display;
dat_buf[0] = display_dat/1000;
display_dat = display_dat%1000;
dat_buf[1] = display_dat/100;
display_dat = display_dat%100;
dat_buf[2] = display_dat/10;
dat_buf[3] = display_dat%10;
}
void setup() {
//set pins to output because they are addressed in the main loop
pinMode(led, OUTPUT);
pinMode(latch, OUTPUT);
pinMode(clock, OUTPUT);
pinMode(data, OUTPUT);
pinMode(K1, INPUT);
pinMode(K2, INPUT);
pinMode(K3, INPUT);
pinMode(K4, INPUT);
pinMode(INPUT1, INPUT);
pinMode(INPUT2, INPUT);
pinMode(INPUT3, INPUT);
pinMode(INPUT4, INPUT);
pinMode(j1, OUTPUT);
pinMode(j2, OUTPUT);
pinMode(j3, OUTPUT);
pinMode(j4, OUTPUT);
FlexiTimer2::set(5, 1.0/1000, TubeDisplay4Bit); // call every 5ms "ticks"
FlexiTimer2::start();
digitalWrite(j1, LOW);
digitalWrite(j2, LOW);
digitalWrite(j3, LOW);
digitalWrite(j4, LOW);
digitalWrite(INPUT1, HIGH);
digitalWrite(INPUT2, HIGH);
digitalWrite(INPUT3, HIGH);
digitalWrite(INPUT4, HIGH);
digitalWrite(K1, HIGH);
digitalWrite(K2, HIGH);
digitalWrite(K3, HIGH);
digitalWrite(K4, HIGH);
key_value = 0;
}
void loop() {
while(1)
{
if(digitalRead(INPUT1)==LOW) {relay1_time_left = relay1_delay_time;digitalWrite(j1, HIGH);digitalWrite(led, HIGH);}else { digitalWrite(led, LOW);}
if(digitalRead(INPUT2)==LOW) {relay2_time_left = relay2_delay_time;digitalWrite(j2, HIGH);digitalWrite(led, HIGH);}else { digitalWrite(led, LOW);}
if(digitalRead(INPUT3)==LOW) {relay3_time_left = relay3_delay_time;digitalWrite(j3, HIGH);digitalWrite(led, HIGH);}else { digitalWrite(led, LOW);}
if(digitalRead(INPUT4)==LOW) {relay4_time_left = relay4_delay_time;digitalWrite(j4, HIGH);digitalWrite(led, HIGH);}else { digitalWrite(led, LOW);}
if (digitalRead(K1)==LOW) {key_value = 0; }
else if(digitalRead(K2)==LOW) {key_value = 1; }
else if(digitalRead(K3)==LOW) {key_value = 2; }
else if(digitalRead(K4)==LOW) {key_value = 3; }
}
}
Неактивний
танунафіг..
Дешевше переписати з нуля.
Стороння людина в простиню з digitalread/digitalwrite без труда не врюхає.
while(1) - можна спокійно викинути, функція loop() сама перезапускається.
FlexiTimer2 - хз що це і як воно працює, підозрюю що якась ліба з таймером. Без вивчення readme таке крпще не використовувати.
TubeDisplay4Bit - судячи з назви, щось пов"язане з дисплеєм. Але всередині там щось з секундами робиться.
В пєчьку! (ц)
Неактивний
У вас є вхід з двома станами: низький / високий рівень (можливий брязкіт контактів поки до уваги не берем).
Є вихід з двома станами: реле вимкнене / увімкнене.
Є внутрішній стан таймера: активний / неактивний.
Це вже дає 8 можливих комбінацій (частина з них потім редукується). Для початку намалюйте діаграму або таблицю переходів. Для кожного переходу визначте умову (стан входу, стан таймера), а також дії, які мають виконатись (увімкнути/вимкнути реле, запустити таймер і т.п.)[/quote dimich]
потрібно щоб при вході низького сигнала з датчика вмикалось реле на умовних 5 секунд навіть якщо тривалість сигналу перевищує 5 секунд щоб реле повторно не вмикалось до моменту поки не буде нового сигналу із датчика ,оскільки зараз приходить сигнал реле вмикається і працює заданий час але якщо по закінченню часу сигнал все ще поступає то реле влючається знову на той же час а потрібно щоб повторно включалось тільки при вході нового сигналу,
Неактивний
танунафіг..
Дешевше переписати з нуля.
Стороння людина в простиню з digitalread/digitalwrite без труда не врюхає.while(1) - можна спокійно викинути, функція loop() сама перезапускається.
FlexiTimer2 - хз що це і як воно працює, підозрюю що якась ліба з таймером. Без вивчення readme таке крпще не використовувати.TubeDisplay4Bit - судячи з назви, щось пов"язане з дисплеєм. Але всередині там щось з секундами робиться.
В пєчьку! (ц)
так,дисплей є
ось такий модуль
Неактивний
Поки реле увімкнене, повторний перехід з високого на низький рівень на вході має перезапускати таймер? Чи стан вхіду має значення тільки після вимкнення реле?
це не має значення оскільки перерва між сигналами із датчика буде більшою за час роботи реле
Неактивний
Для одного реле
bool input1_prev { false };
// в loop():
bool input = (digitalRead(INPUT1)==LOW);
if (input != input1_prev) {
if (input) {
noInterrupts();
relay1_time_left = relay1_delay_time;
digitalWrite(j1, HIGH);
Interrupts();
}
digitalWrite(led, input); // тут один led на 4 канала?
input1_prev = input;
}
Щоб не дублювати код для кожного канала, зробіть масив.
Викиньте "while(1) {...}" із loop().
Можна легко обійтись без отого FlexiTimer2, воно тільки ускладнює програму.
А краще найміть спеціаліста, в якого є час і натхнення, нехай напише вам нормальний код.
Неактивний
Якщо це плата популярна, на неї повинні бути прошивки. на гітхабі пошукайте.