Pull to refresh

Comments 45

К сожалению, в сложной электромагнитной обстановке AVR-ка прекрасно зависает вместе с её сторожевиком.
Так можно практически про любую маломощную схему сказать. 24 вольтовое клацкающее реле с током обмотки по 0.5А тут намного надежнее )))
Делал WDT под свою задачу — удаленные устройства сбора информации на GSM с небольшим бюджетом, когда выезд на место перегрузить зависший модем очень затратное мероприятие
Против вашего решения ничего не имею, даже неиспользование специальных микросхем можно объяснить тем, что нужно было срочно, а тиньки валялись россыпью.
Я скорее пишу как предупреждение тем, кто попытается применить это в других условиях.
Чисто умозрительно, чем проще микросхема, тем лучше справится с помехами, а МК не просты.
В тиньке вообще свой вотчдог есть. Стоит его использовать.

Ну и вообще вся программа написана странно. Заводим таймер, по изменению состояния на входе сбрасываем его счётчик, по переполнению — сбрасываем контролируемое устройство. Всё.

Hint: и да, в качестве таймера можно использовать таймер собственного вотчдога тиньки ;)
У меня как-то AVR стабильно зависал вместе с вочдогом. Из-за наводок. Так что «глупый» внешний вочдог имхо надёжнее.
ХЗ. У меня AVR-ки сами по себе не зависали. Вот всякие там ESP-шки это да. Хотя в области сильных электромагнитных помех я их не ставил. Там как то уже промышленные решения нужны.
Так что «глупый» внешний вочдог имхо надёжнее


Это всегда.
WDT не должен висеть в прерывании и еще есть несколько нюансов. Если помеховая обстановка такая что «ужас-ужас», можно проверять значение всех переменных и чуть что не так перезагружать микроконтроллер. В итоге, как бы не изменилось содержание RAM, микроконтроллер просто не сможет зависнуть.
Умный ватчдог может кроме простого зависания отслеживать сбой в передаче данных, не корректные данные с модема, изменение потребления тока схемой, не корректное питание, защищать от высоких и низких температур, ограничивать количество перезагрузок если они не помогают и еще по мелочам.
Я наверное непонятно выразился.
Происходила полная остановка всего, включая внутренний wdt. Как проверять ram, если тактирование зависло?
Чем умнее внешний вочдог, тем он более подвержен воздействию. И вот нам уже нужны надзиратели за надзирателями.
Происходила полная остановка всего, включая внутренний wdt.

Да, тактирование вачдога от общего клока — слабое место. Хорошо когда в контроллере есть IWDT — совершенно независимый вачдог, тактирующийся от собственного внутреннего генератора :)
Так в AVR независимый генератор для вочдога. Останавливались оба.
Тогда фиг знает… Это какие наводки должны быть чтобы низкочастотный неуправляемый RC-генератор завис :)
Достаточно в схеме индуктивности с высоковольтными выбросами. Да, можно всё развязать гальванически и заэкранировать, но в прототипе было по-простому. Хоть и не на висящих проводах, плата была вытравлена, но не сильно помогло.
По INT0 думал, но решил, что может всякий «мусор» ловить и сбрасываться
Переполнение счетчика можно настроить на 30 секунд?
По INT0 думал, но решил, что может всякий «мусор» ловить и сбрасываться


а) Подавления дребезга и фильтрации мусора у вас в коде нет, так что ваше решение лучше только тем, что на мусор будет реагировать только при его прилёте в момент опроса, что не есть надёжная защита

б) Ничто не мешает на прерываниях сделать не просто ловлю импульса сброса, а определение его ширины и сравнение с минимально допустимой — но тогда будьте добры со стороны контролируемого устройства обеспечить формирование импульсов сброса заданной ширины (и это всё не имеет практического смысла в 99,999 % случаев)

Переполнение счетчика можно настроить на 30 секунд


Вы у меня спрашиваете? Тиньки вы программируете, я их и в руках-то не знаю сколько лет не держал. Это в даташите написано.
А что не так со специализированными сторожевиками, типа ADM6316, ADM823, ADM824?
А STWD100 и прочие аппаратные вотчдоги, коих выпускается полно, благородному дону чем не угодили?..

Ну и если уж делать свой, то зачем такой гроб, как ATTiny13? Есть же PIC10, есть ATTiny4/5/9/10 в SOT23.
Ни вижу, почему бы благородному дону не собрать WDT на тиньке 13 )))
На самом деле вы правы, руководствовался принципом — слепила из того что было.
Тиньки были в наличии, а остальное покупать нужно.

А почему такие тонкие дорожки на плате?

0.33 сигнальные
0.50 питание
Нормально для ЛУТ. Удобно между контактами 2.54 пропускать
Предложу свой вариант программы
#define F_CPU 1200000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>

volatile uint16_t pb1_count;

// Оброботчик прерывания по таймеру TIMER0
ISR(TIM0_OVF_vect){
   pb1_count++;  
}

int main() {
// Устанавливаем выход PB0 и вход PB1 PB2 PB3 PB4 с подтягиванием 
  DDRB = (1 << PB0)| (~(1 << PB1)) | (~(1 << PB2)) | (~(1 << PB4));
  PORTB = ~(1 << PB0) | (1 << PB1) | (1 << PB2) | (1 << PB3) | (1 << PB4);
  
// Определяам время срабатывание таймера по входам PB2,PB3,PB4 (перемычки подтягивают к земле) (период, сек = TM/4 )
  byte i=0;
  if( PINB & (1 << PINB2) ) i+=1;
  if( PINB & (1 << PINB3) ) i+=2;
  if( PINB & (1 << PINB4) ) i+=4;
  uint16_t TM;
  switch (i){
    case 0: TM=4; break;
    case 1: TM=8; break;
    case 2: TM=20; break;
    case 3: TM=40; break;
    case 4: TM=80; break;
    case 5: TM=120; break;
    case 6: TM=240; break;
    default: TM=480;
  }
  
   pb1_count = 0;
   boolean pb1_state = false;
// Отключаем ADC
   PRR = (1<<PRADC); // shut down ADC
// Настраиваем таймер
   TIMSK0 = (1<<TOIE0);  // Включаем таймер TIMER0
   TCCR0B = (1<<CS02) | (1<<CS00); // Пределитель таймера на 1/1024
// Задаем режим сна
   MCUCR &= ~(1<<SM1); // idle mode
   MCUCR &= ~(1<<SM0); // idle mode
   MCUCR |= (1<<SE);
   sei();
   while(1) {
// Зпсываем до прерывания по таймеру    
     asm("sleep");
// Таймер сработал 
// Считываем состояние PB1
    bool pb1 = false;
    if( PINB & (1 << PINB1) )pb1 = true;  
// Если состояние входа инвертировалось, сбрасываем время
    if( pb1 != pb1_state )pb1_count = 0;
    pb1_state = pb1;
// Если превышено время установки таймера
    if( pb1_count >= TM ){
       PORTB |= (1 << PB0);    // digitalWrite(PB0, HIGH);}
       pb1_count = 0;
       //_delay_ms(1000);        // Ждем секунду
       while (pb1_count<4){};
       PORTB &= ~(1 << PB0);   // digitalWrite(PB0, LOW);}
       pb1_count = 0;          // Сбрасываем счетчик
    }
  }      
}


Вот чего я не ожидал.
  byte i=0;
  if( PINB & (1 << PINB2) ) i+=1;
  if( PINB & (1 << PINB3) ) i+=2;
  if( PINB & (1 << PINB4) ) i+=4;
  const PROGMEM uint16_t AT[]={4,8,20,40,80,120,240,480};
  uint16_t TM=AT[i];
Этот код на 40 байт кода и на 8 байт озу больше.
Согласен. Над оптимизацией кода еще работать и работать.
Только вот ваш код у меня меньше не получается. Может быть LTO оптимизатор компилятор мою конструкцию преобразует в что-то еще более компактное?
const uint16_t AT[] PROGMEM ={4,8,20,40,80,120,240,480};
TM=AT[i];
Program Memory Usage: 320 bytes 31,3 % Full
Data Memory Usage: 18 bytes 28,1 % Full

static const uint16_t AT[] PROGMEM ={4,8,20,40,80,120,240,480};
TM=AT[i];

Program Memory Usage: 266 bytes 26,0 % Full
Data Memory Usage: 2 bytes 3,1 % Full
byte i=0;
if( PINB & (1 << PINB2) ) i+=1;
if( PINB & (1 << PINB3) ) i+=2;
if( PINB & (1 << PINB4) ) i+=4;

  uint16_t TM;
  switch ((PINB & 0x1C)){
    case 0: TM=4; break;
    case 1<<2: TM=8; break;
    case 2<<2: TM=20; break;
    case 3<<2: TM=40; break;
    case 4<<2: TM=80; break;
    case 5<<2: TM=120; break;
    case 6<<2: TM=240; break;
    default: TM=480;
  }
static const uint16_t AT[] PROGMEM ={4,8,20,40,80,120,240,480};
TM=AT[((PINB & 0x1C)>>2)];
Ну да, так еще компактнее получится :)
Кстати, если условие свича изменить на такое:
switch ((PINB & 0x1C)>>2){
    case 0: TM=4; break;
    case 1: TM=8; break;
    case 2: TM=20; break;
    case 3: TM=40; break;
    case 4: TM=80; break;
    case 5: TM=120; break;
    case 6: TM=240; break;
    default: TM=480;
  }

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

Вот это да-а-а…
Статью с таким начальным посылом можно дальше не читать?
Да, посыл в корне неверный. Сторожевой таймер — это защита прежде всего от аппаратных сбоев, которые невозможно предотвратить на 100% — всегда есть естественная радиация, и возможны внешние электромагнитные воздействия, от которых не спасут все применяемые на практике меры противодействия им. И применяются они не только в микроконтроллерах, но и в промышленных компьютерах и серверах.
// Сброс таймера (не реже чем 1 на время срабатывания WDT, установленное перемычкой)


И, кстати, да, но нет.

Таймеры на встроенных в контроллер RC-генераторах довольно нестабильны по температуре, поэтому надо смотреть не номинальное время срабатывания у вас на столе (оно же «установленное перемычкой»), а минимально возможное в температурном диапазоне эксплуатации устройства. Оно запросто может отличаться на десятки процентов.
В ATtiny13 4-е поколение встроенного генератора, имеющее неплохую внутреннюю калибровку. Как правила, настройка калибровочных значений идет уже с завода. При необходимости можно произвести самостоятельную температурную калибровку с достижением 1% точности, что для моих задач более чем достаточно
При необходимости можно произвести самостоятельную температурную калибровку с достижением 1% точности


Вы планируете к своему вотчдогу ещё и высокоточный термодатчик добавлять?..
На ресет, как и на другие входы, есть встроенная подияжка
0.1мкф по питанию — в даташите такого нету. А если учесть, что высокочастотной нагрузки нету, то в принципе можно и обойтись
Почему бы не обратиться по подтяжке к даташиту на AVR?
When designing a system where debugWIRE will be used, the following must be observed:
• Pull-Up resistor on the dW/(RESET) line must be in the range of 10k to 20 kΩ. However, the
pull-up resistor is optional.


Только я что-то не понял плюсов подобного принципа работы вачдога — строго периодичное изменение сигнала. Вроде вачдоги всегда строятся на превышении времени между сбросами, а не на строгой синхронности с отслеживаемым девайсом, которому нельзя ни шага влево-вправо от заданного периода сброса.
image
Мой вариант watchdog на ATTINY13 для ESP8266 в формате шилда Wemos D1. Питание подается через разъем USB, программирование задержек осуществляется перемычками на оборотной стороне. В случае зависания ESP8266 ей отключается питание на выбранный интервал времени.
Я на схеме не увидел ни одного конденсатора, шунтирующего питание. Сомневаюсь что этот «костыль для плохих разработчиков» будет надёжнее самого защищаемого устройства.
Повесить МК можно не только по питанию, но и по… выходу, а они здесь выведены напрямую, так что да — вы правы.
Внешний сторожевой таймер это костыль для плохих разработчиков, которые не могут разработать нормально работающую программу для микроконтроллеров или стабильно работающую схему.
Вот где-то тут я начал подозревать, что автор не понимает в вочдогах примерно ничего.

Тем более встроенный WDT имеется у большинства современных микроконтроллеров.
И второе предложение усугубило это подозрение.

Вот что пишет про вочдоги автор, которому действительно можно доверять (Ганссл):
WDTs are not emergency outs, but integral parts of our systems. The WDT is as important as main() or the runtime library, it's an asset that is likely to be used, and maybe used a lot.

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

Подскажите литературу про обязательную внешнюю подтяжку?
В даташите на ATtiny13 сказано, что встроенной подтяжки вполне достаточно
When designing a system where debugWIRE will be used, the following must be observed:
• Pull-Up resistor on the dW/(RESET) line must be in the range of 10k to 20 kΩ. However, the
pull-up resistor is optional.
Это правило хорошего тона, основанное на практике. Если вы можете абсолютно гарантировать что все ваши устройства никогда не попадут в условия наводок, или возможный слёт прошивки для вас неважен — необязательно подтягивать.
Прямо вот с языка сняли про правило хорошего тона.
В даташите на ATtiny13 сазано, что подтяжка на входе Reset имеет сопротивление 30..80 кОм. Да, «на столе» и в «тепличных условиях» этого достаточно, но в более жёстких условиях сопротивление хочется иметь поменьше, чтобы амплитуда импульсов напряжения, наводимых помехами на входы МК, была поменьше, потому и нужен внешний резистор. Я бы его вообще намертво к питанию приколотил, но через Reset ещё debugWire ходит.
Ну, а ёмкость 0.1 мкФ рядом с выводами питания — просто классика жанра. С одной стороны, улучшает стабильность работы самой микросхемы (контур, через который текут высокочастотные токи помех, замыкается через ёмкость, его площадь и индуктивность снижаются, уменьшая вероятность возникновения бросков напряжения, способных завесить микросхему; мы же стабильно работающую схему проектируем), с другой стороны, защищает цепи питания от внешнего мира (опять же, токи помех замыкаются через ёмкость).
Вообще говоря, как минимум в STM32 и EFM32 на ресете есть фильтр, который гарантированно отсекает помехи длительностью до 50 нс, в результате чего встроенной подтяжки вполне достаточно — при отсутствии длинной дорожки до ресета и электроэрозионного станка в радиусе нескольких метров.

В тиньке они тоже есть, но их параметры в явной форме даташит не сообщает.
Sign up to leave a comment.

Articles