Симметричный мультивибратор на Arduino nano Atmega328.

Vandevul
Offline
Зарегистрирован: 23.11.2018

 Друзья, здравствуйте.  Такая штука: собрана приблуда для управления двумя соленоидами. Необходимо, чтобы при замыкании кнопки на землю включались сперва один симметричный мультивибратор, который будет давать сигал на включение реле 1 от первого соленоида на 12 В, далее через задержку включался второй мультивибратор для управления реле 2 от второго соленоида, а первый в этот момент выключался и т.д, т.е. попеременное включение и выключение соленоидов. Время задержки верхнего и нижнего фронта сигналов на вход блока реле регулируется от 500 до 100 мс при помощи потенциометра на 22кОм и значение выводится на LCD дисплей. Логику сделал на FLProg. Первая проблема заключается в том, что сперва блок реле начинает работать нормально, но через продолжительное время нажатия кнопки симметричность включения и выключения релюх нарушается и соленоиды начинают срабатывать хаотично. Запитано все это от компьютерного БП. +12 В на нагрузку и +5 В на контроллер, просадок напряжения нет. Также пробовал это делать на плате Mega уже без соленоида, происходит тоже самое, причем бывает момент, когда они начинают срабатывать асинхронно сразу же в момент нажатия кнопки, с чем это может быть связано и есть ли способы решения данного косяка? Вторая проблема заключается в отображаемой информации времени задержки на LCD дисплее.  Постоянно шакалит последний разряд, плавает на + - 1. Возможно ли это как то стабилизировать и быть может это как раз и является причиной первой проблемы?

1) https://funkyimg.com/i/322Kw.jpg схема коммутации

2)https://funkyimg.com/i/322Kx.png схема в FLProg

3)https://funkyimg.com/i/322Kv.jpg блок реле 

Использовал FLProg 4.0.0 и Arduino IDE 1.8.1

Код в arduino IDE:

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C _lcd1(0x3F, 16, 2);
int _dispTempLength1=0;
boolean _isNeedClearDisp1;

int _disp2oldLength = 0;
bool _tim1I = 0;
bool _tim1O = 0;
unsigned long _tim1P = 0UL;
int _disp1oldLength = 0;
bool _bounseInputD2S = 0;
bool _bounseInputD2O = 0;
unsigned long _bounseInputD2P = 0UL;
bool _gen1I = 0;
bool _gen1O = 0;
unsigned long _gen1P = 0UL;
bool _gen2I = 0;
bool _gen2O = 0;
unsigned long _gen2P = 0UL;
void setup()
{
Wire.begin();
delay(10);
pinMode(2, INPUT_PULLUP); 
pinMode(4, OUTPUT); 
pinMode(7, OUTPUT); 

_lcd1.init();
_lcd1.backlight();
_bounseInputD2O =  digitalRead(2);
}
void loop()
{if (_isNeedClearDisp1) {_lcd1.clear(); _isNeedClearDisp1= 0;}

bool  _bounceInputTmpD2 =  (digitalRead (2));

if (_bounseInputD2S) 
    {
     if (millis() >= (_bounseInputD2P + 40)) 
         {_bounseInputD2O= _bounceInputTmpD2; _bounseInputD2S=0;}
     }
else
    {
     if (_bounceInputTmpD2 != _bounseInputD2O )
         {_bounseInputD2S=1; _bounseInputD2P = millis();} 
      } 




//Плата:1
if (1) {
_dispTempLength1 = (((String((map(( (analogRead (2))), (0), (1023), (100), (500))), DEC)))).length();
if (_disp1oldLength > _dispTempLength1) {_isNeedClearDisp1 = 1;} 
_disp1oldLength = _dispTempLength1;
_lcd1.setCursor(int((16 - _dispTempLength1)/2), 0);
_lcd1.print(((String((map(( (analogRead (2))), (0), (1023), (100), (500))), DEC))));
} else {
if (_disp1oldLength > 0) {_isNeedClearDisp1 = 1; _disp1oldLength = 0;} 
}
if (!(_bounseInputD2O))
{ if (_tim1I) { if (_isTimer(_tim1P, (map(( (analogRead (2))), (0), (1023), (100), (500))))) {_tim1O = 1;}} else {_tim1I =1; _tim1P = millis();}} else {_tim1O = 0; _tim1I = 0;}
if (_tim1O) { if (! _gen2I) { _gen2I = 1; _gen2O = 1; _gen2P = millis(); } } else { _gen2I = 0 ; _gen2O= 0;}
 if (_gen2I) {  if ( _isTimer ( _gen2P , (map(( (analogRead (2))), (0), (1023), (100), (500))) )) { _gen2P = millis(); _gen2O = ! _gen2O;}}
digitalWrite(7, !(_gen2O));
if (!(_bounseInputD2O)) { if (! _gen1I) { _gen1I = 1; _gen1O = 1; _gen1P = millis(); } } else { _gen1I = 0 ; _gen1O= 0;}
 if (_gen1I) {  if ( _isTimer ( _gen1P , (map(( (analogRead (2))), (0), (1023), (100), (500))) )) { _gen1P = millis(); _gen1O = ! _gen1O;}}
digitalWrite(4, !(_gen1O));
if (1) {
_dispTempLength1 = ((String("Pulse time (ms)"))).length();
if (_disp2oldLength > _dispTempLength1) {_isNeedClearDisp1 = 1;} 
_disp2oldLength = _dispTempLength1;
_lcd1.setCursor(int((16 - _dispTempLength1)/2), 1);
_lcd1.print((String("Pulse time (ms)")));
} else {
if (_disp2oldLength > 0) {_isNeedClearDisp1 = 1; _disp2oldLength = 0;} 
}




}
bool _isTimer(unsigned long startTime, unsigned long period )
  {
  unsigned long currentTime;
currentTime = millis();
if (currentTime>= startTime) {return (currentTime>=(startTime + period));} else {return (currentTime >=(4294967295-startTime+period));}
  }

 

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

С ФЛПрогом Вам здесь никто не поможет - не жалуют его тут.

Так что либо ищите форум по ФЛПрогу, либо (если Вам уже исполнилось хотя бы 10 лет) переходите на нормальный язык программирования.

bwn
Offline
Зарегистрирован: 25.08.2014

Vandevul пишет:

 Друзья, здравствуйте.  Такая штука: собрана приблуда для управления двумя соленоидами. Необходимо, чтобы при замыкании кнопки на землю включались сперва один симметричный мультивибратор, который будет давать сигал на включение реле 1 от первого соленоида на 12 В, далее через задержку включался второй мультивибратор для управления реле 2 от второго соленоида, а первый в этот момент выключался и т.д, т.е. попеременное включение и выключение соленоидов. Время задержки верхнего и нижнего фронта сигналов на вход блока реле регулируется от 500 до 100 мс при помощи потенциометра на 22кОм и значение выводится на LCD дисплей. Логику сделал на FLProg. Первая проблема заключается в том, что сперва блок реле начинает работать нормально, но через продолжительное время нажатия кнопки симметричность включения и выключения релюх нарушается и соленоиды начинают срабатывать хаотично. 

Про нормальный язык выше уже написали, там кода, без экрана, десять строчек и состоит он из analogRead, map, digitalWrite и простит меня бог, delay.
Бегающий разряд, это природное свойство потенциометра, странно, что только на единицу.
А вот тому хаду, который вас так кнопку научил включать, пургену в чай насыпьте.)))) (Не, виноват, там флпрога пуллапа вставила. Пурген отменяем. Хотя ведь могла и не вставить). Т.к. внутренний резистор весьма большого номинала, вполне может от срабатывания реле колбасить.

Ну а борьба с переполненным миллисом, как всегда, вне конкуренции.))))

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

bwn пишет:

Ну а борьба с переполненным миллисом, как всегда, вне конкуренции.))))

Это просто фирменная фишка FLProg - как песня "На речке, на речке ..." обязательно появляется во всех фильмах Данелия, так и эта борьба -  во всех произведениях FLprog.

Vandevul
Offline
Зарегистрирован: 23.11.2018

 Господа, насколько я понял, Вы утверждаете, что написав правильно программу в среде IDE на С, используя функции analogRead, map, digitalWrite, delay и т.д. момент с рассинхроном срабатывания реле можно избежать?

 Бегающий разряд удалось убрать подав 12 вольт на вход контроллера. Теперь отображает все четко без мерцания.

 Другой момент. Решил запитать LCD дисплей 5 Вольтами с БП (не через стабилизатор с контроллера), чтобы лишний раз не нагружать Nano, в итоге сперва все отлично показывает, регулировка значений с потенциометра отображается корректно, но стоит нажать кнопку для начала работы реле, через 20 секунд вполне корректной работы контроллер зависает, оставляя открытым или закрытым один из реле. SCL SDA подтянул к +5 Вольт через резисторы 10кОм. Если подключать LCD к питанию с контроллера то иногда начинает мерцать подсветка. 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Vandevul пишет:

насколько я понял, Вы утверждаете, что написав правильно программу в среде IDE на С, используя функции analogRead, map, digitalWrite, delay и т.д. момент с рассинхроном срабатывания реле можно избежать?

Нет.

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

Что до второй части Вашего поста - запостите его на тот форум, на который Вы выкладывали схему. Там Вам смогут что-то разумное сказать. Здесь же - никак. Разве что, я вот заметил:

Vandevul пишет:

SCL SDA подтянул к +5 Вольт через резисторы 10кОм. 

Много! См. п. 22.5.2 даташита и таблицу 29-14 там же.

Vandevul
Offline
Зарегистрирован: 23.11.2018

ЕвгенийП пишет:

Нет.

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

 Моё почтение, Вы меняя воодушевили на то, чтобы разбираться с кодом. Просто я склонялся в сторону аппаратной неисправности. 

 Если Вас не затруднит, не могли бы скинуть ссылку на даташит, на который Вы указали?

 

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Так я имел в виду даташит на ATmega328P, которая стоит в унах, нанах и т.п. (только не говорите, что у Вас DUE - такое надо в первом посте писать! :-)

Vandevul
Offline
Зарегистрирован: 23.11.2018

Большое спасибо! У меня именно такой чип, просто я в другом формате даташит скачал и соответственно не находил указанные Вами пункты)  Попробую подтянуть на 1.5кОм.