Схема нормально открытого транзисторного ключа

Pyotr
Offline
Зарегистрирован: 12.03.2014

Leopoll пишет:

Для интереса попробовал. Резистор 2.2К, конденсатор 0.33Мкф. Забабахал 4000Гц. На жидкость, в отличие от моих 10Гц, не реагирует. При полном замыкании показывает разность почему-то -150 (При размыкании правильные 1022).

Конечно, буду еще пробовать.  Интересно.

volatile long ACD_H;
volatile long ACD_L;
volatile bool flag;
volatile unsigned int i;
void setup() {
  Serial.begin (9600);
  Serial.println ("Launch");
  pinMode ( 7, OUTPUT );
  pinMode ( A0, INPUT );
  
  cli();
  TCCR3A = 0;
  TCCR3B = 0;
  TCCR3B = (1<<WGM32); //CTC mode
  TCCR3B |= (1<<CS11); //делитель CLK / 8
  OCR3A = 499;
  TIMSK3 |= (1<<OCIE3A); //enable timer compare interrupt
  sei();

}

void loop() {
 Serial.print (i);
 Serial.print ("  ");
 Serial.print (ACD_H/2000);Serial.print ("  ");
 Serial.print (ACD_L/2000);Serial.print ("  ");
 Serial.println ( (ACD_H-ACD_L)*2/i );    // Результат от 1023 до -150
 i = 0;
 ACD_L = 0;
 ACD_H = 0;
 delay (1000);

}
ISR(TIMER3_COMPA_vect){
  
  i++;
  if (flag) {
    digitalWrite ( 7, LOW );
    ACD_L += analogRead (A0);
  }
  else {
    digitalWrite ( 7, HIGH );
    ACD_H += analogRead (A0);
  }
  flag = !flag;
}
Launch
0  0  0  1023
4000  1023  0  1022
4000  1023  0  1023
4000  1023  0  1022
4000  1023  0  1023
4000  1023  0  1023
4000  1022  0  1022
4000  1023  0  1022
4000  1023  0  1022
4000  1022  0  1022
4000  1021  0  1020
4000  723  299  423
4000  434  587  -152
4000  434  587  -153
4001  433  587  -153
4000  434  587  -153
4000  434  587  -153
4000  434  587  -153
4000  434  587  -152
4000  434  587  -153

 

В обработчике нужно завести счетчик количества измерений. При достижении например 10, запрещать суммирование АЦП, а в луп() проверять этот счетчик, как досчитал до 10, делать вычисления и печать.

А вообще можно аппаратно переключать пин. Например сделать ШИМ на таймере 2 (ардуино УНО и подобные) 4 кГц 50%. Навскидку предделитель 8 вместо 64. В прерывании по переполнению читать высокий уровень, а в прерывании по совпадению - низкий. Если через регистры, то это вообще в фоновом режиме. Данные складывать в кольцевой буфер, а в ЛУП() когда надо суммировать элементы массивов, предварительно запретив прерывания, делать вычисления и работать с результатом.

Leopoll
Offline
Зарегистрирован: 16.06.2016

У меня Мега, таймер2 занят tone(). Поэтому третий использую. Как думаешь, почему на жидкость то не реагирует? И разве -150 это нормально?

Pyotr
Offline
Зарегистрирован: 12.03.2014

Leopoll пишет:

У меня Мега, таймер2 занят tone(). Поэтому третий использую. Как думаешь, почему на жидкость то не реагирует? И разве -150 это нормально?

На жидкость реагирует (что за жидкость, значение  ЕС??), а вот считает/измеряет неправильно. Поэтому и отрицательные значения, что ненормально.

Leopoll
Offline
Зарегистрирован: 16.06.2016

Пока попробовал реализовать первый вариант, с внешним генератором. В принципе работает, но не особо красиво. Шунт поставил 100К, там в реальности все же скорее единицы мкА, а не десятки. Снимал с + и - диодного моста через 1К, показания вычитал.   Результат примерно правильный, но сильно скачет. кроме того, часто проскакивают минимальные (ноль) и максимально возможные значения (600-700), тогда как правильный диапазон 30-80. 

Плюс, поскольку питание у ардуино и мультивибратора 10Гц общее, идут наводки на МК и он вырубается. Может и показания из-за этого скачут? Как правильно их изолировать?

Duino A.R.
Offline
Зарегистрирован: 25.05.2015

Leopoll пишет:
Плюс, поскольку питание у ардуино и мультивибратора 10Гц общее, идут наводки на МК и он вырубается. Может и показания из-за этого скачут? Как правильно их изолировать?

Попробуйте, для начала, запитать МК от отдельного ИП, начиная от сети 220 В. Посмотрите, какая часть неприятностей пропадёт, а какая останется.

Leopoll
Offline
Зарегистрирован: 16.06.2016

Если земли не соединить, на входах вообще полная каша.

Duino A.R.
Offline
Зарегистрирован: 25.05.2015

Leopoll пишет:
Если земли не соединить, на входах вообще полная каша.

Так и должно быть. Ардуина измеряет напряжение на входах относительно собственного общего провода (GND). Земли нужно соединять обязательно. Иногда влияет даже конкретная точка (должна быть одна!) подключения общего провода ("земли") МК и остальной схемы. Вот кроме "земли" и измерительных аналоговых входов других никаких связей быть не должно. Т.е. задайте питание МК от отдельного ИП, начиная от сети 220 В.

Для гарантии можно и аналоговые входы отключить и посмотреть, будет МК сбиваться или нет. Если так будет работать без сбоев, подключить измерительные входы.

Buldakov
Offline
Зарегистрирован: 17.01.2016

Прочитал ветку и ничего не понял. При чем тут схема нормально открытого ключа.

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

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

1.Например есть 2 источника напряжения питания +12в. от одного трансформатора.

2. При включении трансформатора в сеть питание подается на ардуино.

3.После инициализации в setup прописывается постоянный сигнал на каком нибудь выходе.

4. Этот сигнал подается на аналоговый таймер (длительность импульса должна быть более мин. времени включения платы и инициализации) например 10 сек. Делается например на триггере шмита с RC цепочкой.

5. После этого аналоговый таймер подает питание на выходные ключи и они начнут передавать сигналы с ардуино на внешнее устройство.

Замечание: Данный вариант подходит только для устранения ложных сигналов при включении. Он не подходит с вариантом когда питание пропало или плата зависла. Для этого варианта необходимо на выводе управления задать какую нибудь частоту. Если частота есть - то сигнал проходит через выходные ключи. Если сигнала нет, или если это лог 0, или лог1. то он должен блокировать выходные промежуточные ключи. Данный вариант сложнее реализовать электрически, но он будет работать почти всегда. Но и тут есть ограничения.

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

Buldakov пишет:

Прочитал ветку и ничего не понял. При чем тут схема нормально открытого ключа.

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

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

1.Например есть 2 источника напряжения питания +12в. от одного трансформатора.

2. При включении трансформатора в сеть питание подается на ардуино.

3.После инициализации в setup прописывается постоянный сигнал на каком нибудь выходе.

4. Этот сигнал подается на аналоговый таймер (длительность импульса должна быть более мин. времени включения платы и инициализации) например 10 сек. Делается например на триггере шмита с RC цепочкой.

5. После этого аналоговый таймер подает питание на выходные ключи и они начнут передавать сигналы с ардуино на внешнее устройство.

Это все от лукавого.

Правильная схема должна сама формировать правильное состояние инициализации ключей при высокоимпедансном состоянии выходов контроллера.

Leopoll
Offline
Зарегистрирован: 16.06.2016

Pyotr пишет:

На жидкость реагирует (что за жидкость, значение  ЕС??), а вот считает/измеряет неправильно. Поэтому и отрицательные значения, что ненормально.

Поменял алгоритм. То же самое.

volatile long ACD_H;
volatile long ACD_L;
volatile bool flag;
volatile  long i;
unsigned long timer;
void setup() {
  Serial.begin (9600);
  Serial.println ("Lauch");
  pinMode ( 7, OUTPUT );
  pinMode ( A0, INPUT );
  pinMode (LEDPIN, OUTPUT );
  cli();
  TCCR3A = 0;
  TCCR3B = 0;
  TCCR3B = (1<<WGM32); //CTC mode
  TCCR3B |= (1<<CS11); //делитель CLK / 8
  OCR3A = 499;
  TIMSK3 |= (1<<OCIE3A); //enable timer compare interrupt
  sei();

}

void loop() {
 if ( i == 4000 ){
 Serial.print (i);
 Serial.print ("  ");
 Serial.print ( (i*1000)/(millis()-timer) );    // Частота в Гц
 Serial.print ("  ");
 Serial.print (ACD_H*2/i);Serial.print ("  ");
 Serial.print (ACD_L*2/i);Serial.print ("  ");
 Serial.println ( (ACD_H-ACD_L)*2/i );            // Результат
 timer = millis();
 i = 0;
 ACD_L = 0;
 ACD_H = 0;
 }
 

}
ISR(TIMER3_COMPA_vect){
  
  
  if ( i < 4000 ) {
    i++;
  if (flag) {
    digitalWrite ( 7, LOW );
    ACD_L += analogRead (A0);
  }
  else {
    digitalWrite ( 7, HIGH );
    ACD_H += analogRead (A0);
  }
  flag = !flag;
  }
}
4000  3996  1022  0  1022
4000  4004  1022  0  1022
4000  3996  1022  0  1022
4000  4004  1022  0  1022
4000  3996  627  392  235
4000  4004  433  584  -151
4000  4000  433  584  -151
4000  4000  433  584  -151
4000  4000  433  584  -151
4000  3996  433  584  -151

Контакты сначала разомкнуты, потом замкнуты. При понижении частоты ошибка возрастает. Частота 58Гц.

40  58  1023  0  1023
40  58  1023  0  1023
40  58  1023  0  1023
40  58  1023  0  1023
40  58  1023  49  973
40  58  26  993  -967
40  58  26  993  -967
40  58  26  993  -967
40  58  25  993  -968
40  58  26  994  -968

При погружении в  жидкость (спирт :) ) снижается ACD_H на единицу. Что очень мало. 

Гриша
Offline
Зарегистрирован: 27.04.2014

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

Pyotr
Offline
Зарегистрирован: 12.03.2014

Leopoll пишет:

При погружении в  жидкость (спирт :) ) снижается ACD_H на единицу. Что очень мало. 

Так спирт не проводит ток. Или что-то не договариваешь. А электропроводность воды единицы мкСм/см.

Для строк 33-35 нужно запрещать прерывания.

И в конце измерений А0 устанавливать на вход, а перед началом измерений снова как выход.

 

Leopoll
Offline
Зарегистрирован: 16.06.2016

Pyotr пишет:

Для строк 33-35 нужно запрещать прерывания.

И в конце измерений А0 устанавливать на вход, а перед началом измерений снова как выход.

Замечания безусловно верные, но это ничего не изменило. 

осциллограф действительно странен:

Таймер 4000 раз в секунду.

Контакты разомкнуты, измерение между сигналом и землей

Контакты замкнуты

Контакты разомкнуты, между сигналом и входом А0

Контакты замкнуты

Pyotr пишет:

Так спирт не проводит ток. 

Там же целых 4 процента воды ;)

На внешнем генераторе 10 Гц были замечательные результаты - при диапазоне напряжения от 1 до 5В, спирт показывал 2.5В, спирт с примесями или разбавленный - 3.5В. Вот только стабильности нет при выводе на АЦП. 

Здесь стабильность полная, но показывает не то. Возможно чувствительность надо регулировать резистором и конденсатором. То что значения отрицательные это ладно, но почему так далеко от нуля (-150)?

Гриша
Offline
Зарегистрирован: 27.04.2014

как минимум, начните давить наводку 50Гц, в плоть до фильтрации сигнала ФВЧ. Чего у вас там на 10Гц измерялось вообще не ясно т.к. 10 и 50 Гц при таких амплитудах...  как понимаю, ваш полезный сигнал (напряжение и ток) на последних двух картинках. В одном случае сигнал напряжения показан штриховкой, а во втором (ток) пиками на 50 Гц.  Как минимум, сигнал есть, осталось понять, что с ним делать точнее как его понимать   

Pyotr
Offline
Зарегистрирован: 12.03.2014

Leopoll пишет:

 Возможно чувствительность надо регулировать резистором и конденсатором. То что значения отрицательные это ладно, но почему так далеко от нуля (-150)?

Вот для этого я раньше и спрашивал - что за жидкость?

Номинал резистора, указанный мной, для ЕС=100...5000 мкСМ/см. Для твоих значений (0...100) возьми резистор 22-47 кОм. Конденсатор оставь прежним. 
Электроды надо из нержавейки площадью несколько см2, например 2х2см. Между электродами 5-10 мм. Провода к ним в экран. Экран на землю со стороны ардуино.

На выход поставить резистивный делитель 47 на 47 кОм, чтоб при переключении пина на вход, он не болтался и не ловил наводки.

И вообще для начала попробуй без таймера и прерываний. 
Тупо в луп() пин как выход,  переключил пин в ХАЙ, задержка 10-100 мкс (попробуй. А лучше вместо задержки читай АЦП, но результат выкинь.), чтение АЦП хай, переключил в ЛОУ, опять задержка ( читай АЦП, но результат выкинь.), чтение АЦП лоу. 20-30 измерений, пин как вход и вывод в сериал. Тип переменных инт достаточно. Выводи как есть без перерасчетов.

Leopoll
Offline
Зарегистрирован: 16.06.2016

Продолжаю потихоньку. 
Пока тестирую просто на замыкание размыкание. Лучшие результаты получаются, если увеличивать частоту и увеличивать номинал резистора. Тогда можно получить близко к 1023 и 0. Резистивный делитель (если ставить его между цифровым выводом и резистором 2.2к) понижает верхнюю границу и только. 

Pyotr пишет:

И вообще для начала попробуй без таймера и прерываний. 

Пробую. Результат по по прежнему зависит от частоты.

 unsigned long t = millis();
  int a;
  int a1;
  int a2;
  bool flag1 = true;
  bool flag2 = false;
  int i ;
void setup() {
  // put your setup code here, to run once:
  Serial.begin (9600);
  Serial.println ("Launch");
  pinMode ( 7, OUTPUT );
  digitalWrite ( 7, HIGH );
  i = 10;
}


void loop() {
  // put your main code here, to run repeatedly:
 a = analogRead( A0 );
if (( millis() - t ) >i ){
  if ( flag1){
  Serial.print ("Msec ");
  Serial.print ( i );
  a1 = a;
  Serial.print (" High ");
  Serial.print ( a1 );
  
  digitalWrite ( 7, LOW );
  flag1 = false;
  flag2 = true;
}}
if (( millis() - t ) >(i*2) ){
  if (flag2){
  a2 = a;
  Serial.print ( " Low " );
  Serial.print ( a2 );
  Serial.print (" Dif ");
  Serial.println (a1-a2);
  t = millis();
  digitalWrite ( 7, HIGH );
  flag2 = false;
  flag1 = true;
}}

  
}

В результатах везде взят переход от разомкнутого состояния контактов к замкнутому. Резистор 47к.

Msec 5 High 1023 Low 1023 Dif 0
Msec 5 High 1023 Low 1023 Dif 0
Msec 5 High 1023 Low 1023 Dif 0
Msec 5 High 673 Low 673 Dif 0
Msec 5 High 491 Low 491 Dif 0
Msec 5 High 488 Low 488 Dif 0
Msec 10 High 1019 Low 1 Dif 1018
Msec 10 High 1020 Low 3 Dif 1017
Msec 10 High 1023 Low 0 Dif 1023
Msec 10 High 1023 Low 0 Dif 1023
Msec 10 High 1023 Low 0 Dif 1023
Msec 10 High 1020 Low 7 Dif 1013
Msec 10 High 1023 Low 0 Dif 1023
Msec 10 High 1023 Low 0 Dif 1023
Msec 10 High 1023 Low 327 Dif 696
Msec 10 High 574 Low 538 Dif 36
Msec 10 High 607 Low 578 Dif 29
Msec 10 High 600 Low 598 Dif 2
Msec 10 High 621 Low 630 Dif -9
Msec 10 High 622 Low 569 Dif 53
Msec 10 High 613 Low 584 Dif 29
Msec 10 High 626 Low 567 Dif 59
Msec 20 High 1020 Low 0 Dif 1020
Msec 20 High 1023 Low 0 Dif 1023
Msec 20 High 1023 Low 0 Dif 1023
Msec 20 High 1023 Low 0 Dif 1023
Msec 20 High 1023 Low 0 Dif 1023
Msec 20 High 1023 Low 4 Dif 1019
Msec 20 High 881 Low 278 Dif 603
Msec 20 High 814 Low 255 Dif 559
Msec 20 High 810 Low 239 Dif 571
Msec 20 High 807 Low 237 Dif 570
Msec 20 High 792 Low 232 Dif 560
Msec 20 High 789 Low 232 Dif 557
Msec 20 High 788 Low 232 Dif 556
Msec 100 High 1023 Low 0 Dif 1023
Msec 100 High 1023 Low 0 Dif 1023
Msec 100 High 1022 Low 0 Dif 1022
Msec 100 High 1023 Low 0 Dif 1023
Msec 100 High 1023 Low 0 Dif 1023
Msec 100 High 1023 Low 1 Dif 1022
Msec 100 High 1022 Low 0 Dif 1022
Msec 100 High 1021 Low 0 Dif 1021
Msec 100 High 1021 Low 1 Dif 1020
Msec 100 High 1020 Low 0 Dif 1020

Не понял, зачем переключать аналоговый вход на OUTPUT. 

pinMode ( A0, OUTPUT ); приводит к этому.

Msec 2 High 7 Low 7 Dif 0
Msec 2 High 7 Low 7 Dif 0
Msec 2 High 6 Low 6 Dif 0
Msec 2 High 7 Low 7 Dif 0

Это при резисторе 2К, если 47К то просто везде нули. 

П.С. В принципе, при резисторе 150К разница между двумя моими контрольным жидкостями около 100. Можно пытаться работать. Но хотелось бы разобраться и быть уверенным в стабильности результата. 

Гриша
Offline
Зарегистрирован: 27.04.2014

Leopoll пишет:

Пробую. Результат по по прежнему зависит от частоты.

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

Pyotr
Offline
Зарегистрирован: 12.03.2014

Вот примерный код о котором я говорил

#define TOT_MEAS 10
void setup() {
  Serial.begin (9600);
  Serial.print ("High");
  Serial.print ("\t" );
  Serial.print ( "Low" );
  Serial.print ("\t" );
  Serial.println ("Dif");
}
void loop() {
 word valLow[TOT_MEAS] = {0}, valHigh[TOT_MEAS] = {0}; 
 pinMode ( 7, OUTPUT ); 
 for(byte i=0; i<TOT_MEAS; i++){
  digitalWrite ( 7, HIGH );
  analogRead( A0 );
  valHigh[i] = analogRead( A0 );  
  digitalWrite ( 7, LOW );
  analogRead( A0 );
  valLow[i] = analogRead( A0 ); 
 }
 pinMode ( 7, INPUT ); 
  
  for(byte i=0; i<TOT_MEAS; i++){
    Serial.print (valLow[i]);
    Serial.print ("\t" );
    Serial.print (valHigh[i]);
    Serial.print ("\t" );
    Serial.println (valHigh[i] - valLow[i]); 
  }
  Serial.println();
  delay(500);  
}

 

Leopoll
Offline
Зарегистрирован: 16.06.2016

Pyotr пишет:
Вот примерный код о котором я говорил

Дошли наконец руки. Ваш код действительно дает стабильный результат при любом значении TOT_MEAS.

511	512	1
510	512	2
510	511	1
510	512	2
511	511	0

0	948	948
0	987	987
0	997	997
0	988	988
0	996	996

Странно. Не понимаю, где принципиальная разница между моим и вашим кодом. И как тогда делать рабочий скетч на таймере.

Гриша
Offline
Зарегистрирован: 27.04.2014

Leopoll пишет:

Странно. Не понимаю, где принципиальная разница между моим и вашим кодом. И как тогда делать рабочий скетч на таймере.

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

пост 116. строки измерения 20,29 и 41 имеют мусор (для измерения) между событиями.

в посте 118 сперва происходят измерения с записью в массив строки 13-20, а уже потом вывод результатов строки 23-28.

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

вам известен смысл слова тайминг? тайминг (значение 1)

если ссылка лагает - https://ru.wiktionary.org/wiki/тайминг

Pyotr
Offline
Зарегистрирован: 12.03.2014

Leopoll, ну если мой пример работает, то оформить этот код в функцию и вызывать ее, например, раз в сек. ЛУП() будет тормозиться на 1-2 мс. Или это критично?

Про таймер я писал пост #101 .