Watchog в Arduino Pro Micro

Viator
Offline
Зарегистрирован: 18.01.2019

Здравствуйте! Прошу совета знатоков.

Возникло желание применить ардуину для считывания данных с одного прибора.

Имеется плата Arduino Pro Micro.

Алгоритм приёма данных простой. Микроконтроллер ардуины периодически опрашивает линию строба данных и при появлении строба принимает байт с шины данных и пересылает его в компьютер по каналу USB. 

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

Для пробы взял такой скетч (заимствовано с сайта https://uscr.ru/arduino-watchdog-bootloop-i-proshivka-zagruzchika-optiboot/, с незначительными изменениями):



// взято отсюда: https://uscr.ru/arduino-watchdog-bootloop-i-proshivka-zagruzchika-optiboot/

#include <avr/wdt.h>

void setup() {

  wdt_disable(); // бесполезная строка, до которой не доходит выполнение при bootloop

  pinMode(17, OUTPUT);  // initialize digital pin 17 (RXLED) as an output
  pinMode( 7, OUTPUT);      
  pinMode( 4, INPUT_PULLUP);
  pinMode( 6, INPUT_PULLUP);
  pinMode(18, INPUT_PULLUP);
  pinMode(19, INPUT_PULLUP);
  pinMode(20, INPUT_PULLUP);
  pinMode(21, INPUT_PULLUP);
  pinMode(10, INPUT_PULLUP);
  pinMode(14, INPUT_PULLUP);
  pinMode(16, INPUT_PULLUP);
  pinMode(15, INPUT_PULLUP);
  pinMode( 1, INPUT_PULLUP);
  pinMode( 0, INPUT_PULLUP);
  pinMode( 2, INPUT_PULLUP);
  pinMode( 3, INPUT_PULLUP);
  pinMode( 5, INPUT_PULLUP);
  pinMode( 8, INPUT_PULLUP);
  pinMode( 9, INPUT_PULLUP);


  delay(5000); // Задержка, чтобы было время перепрошить устройство в случае bootloop

  Serial.begin(9600);
  Serial.println("Setup..");

  wdt_enable (WDTO_8S); // Для тестов не рекомендуется устанавливать значение менее 8 сек.
  Serial.println("Watchdog enabled.");
}

int timer = 0;

void loop(){

// Каждую секунду мигаем светодиодом и значение счетчика пишем в Serial
  if(!(millis()%1000)){
  timer++;
  Serial.println(timer);
  digitalWrite(17, digitalRead(17)==1?0:1); delay(1);
  }
// wdt_reset();
} 

В результате: после подачи питания (втыканием ардуины в разъём USB компьютера) всё работает, периодически происходит перезагрузка программы по watchdog'у. Стоит включить монитор порта (ардуинский либо гипертерминал) - watchdog пропадает.

Что можно сделать?

 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

А откуда видно, что ватчдог работает?

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

ua6em пишет:

А откуда видно, что ватчдог работает?

Дак Ардуина гавкает же. Коротко и страшно.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

DetSimen пишет:

ua6em пишет:

А откуда видно, что ватчдог работает?

Дак Ардуина гавкает же. Коротко и страшно.

А!!!
Я для проверки поддержки ватчдога использую этот скетч (для нано)
 

// modify Victor UA6EM 09.12.2018
// To activity WDT Timer Pse connect Pin8 to GND

#include <avr/wdt.h>
unsigned int timer = 0;

  void setup() {
  wdt_disable(); 
  pinMode(8,INPUT_PULLUP);
 
  Serial.begin(9600);
  Serial.println("Setup..");
  
  Serial.println("Wait  sec..");
  delay(1000); 
  if(digitalRead(8) == LOW){
  wdt_enable (WDTO_8S); // Для тестов не рекомендуется устанавливать значение менее 8 сек.
  Serial.println("Watchdog enabled.");
      }else{
            Serial.println("Watchdog DISABLE.");
           }
       }

void loop(){
  // Каждую секунду мигаем светодиодом и значение счетчика пишем в Serial
  if(!(millis()%1000)){ // каждый 1000 будет давать 0 (FALSE) а (!FALSE) есть TRUE )))
    timer++;
    Serial.println(timer);
    digitalWrite(13, digitalRead(13)==1?0:1); delay(1); //
  }
}

 

Viator
Offline
Зарегистрирован: 18.01.2019

Когда watchdog не работает - светодиод мигает периодически, когда работает - пачками. На глаз - в соответствии с ожидаемым.

b707
Offline
Зарегистрирован: 26.05.2017

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

ИМХО, вы что-то другое пытались сделать, но у вас явно не вышло.

b707
Offline
Зарегистрирован: 26.05.2017

Viator пишет:

Когда watchdog не работает - светодиод мигает периодически, когда работает - пачками. На глаз - в соответствии с ожидаемым.

интересно, а с чего мигание пачками является "ожидаемым"? логику работы этого кода можете словами обьяснить?

VladimirTsibrov
Offline
Зарегистрирован: 05.03.2019

Viator пишет:

Микроконтроллер ардуины периодически опрашивает линию строба данных и при появлении строба принимает байт с шины данных и пересылает его в компьютер по каналу USB. 

Естественно, следует предусмотреть выход из цикла опроса, если строб не появляется за заданное время.

В смысле выход из цикла опроса? Вы же написали: периодически опрашивает линию строба, есть данные - принимает байт, нет - ну и нет. Зачем wdt?

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

VladimirTsibrov пишет:

Зачем wdt?

А вдруг зависла (С)

b707
Offline
Зарегистрирован: 26.05.2017

VladimirTsibrov пишет:

В смысле выход из цикла опроса? Вы же написали: периодически опрашивает линию строба, есть данные - принимает байт, нет - ну и нет. Зачем wdt?

думаю, это продвинутый вариант вопроса "Помогите выйти из цикла while (или for)", которые тут периодически возникают.

Автор пишет блокирующий цикл, а потом не знает, как выполнять остальной код программы :) А этот ТС продвинутый - догадался wdt приспособить для выхода из цикла.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

sadman41 пишет:

VladimirTsibrov пишет:

Зачем wdt?

А вдруг зависла (С)

вам не нравится вачдог, да вы его готовить не умеете...
PS москвичи из СМУ радиострой сожрали у нас всех собак еже что, умели готовить )))

Viator
Offline
Зарегистрирован: 18.01.2019

Строб короткий, и кроме проверки его состояния, в цикле ничего сделать не удаётся. Если строб появился - выход на продолжение программы, если нет - выход только по прерыванию.

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

При подключенном USB с поднятым CDC драйвером на стороне хоста (сиречь "открытым монитором" ;) ), каждое прерываение USB, а хост их рождает регулярно, проверяя "жив ли пациент", производит ресет таймера вочдога. Если это тебе мешает - меняй логику программы или выводи диагностику не через USB.

VladimirTsibrov
Offline
Зарегистрирован: 05.03.2019

Viator пишет:

Если строб появился - выход на продолжение программы, если нет - выход только по прерыванию.

Так если строб не появился и мы перезагрузили микроконтроллер, мы же опять вернемся в этот цикл, не?

А этот короткий строб не появится как раз когда мы решили перезагрузиться?

Viator
Offline
Зарегистрирован: 18.01.2019

Когда watchdog работает, программа с периодом 8 с уходит на перезапуск, при этом в миганиях появляется дополнительно 5-секундная пауза (оператор delay(5000) в процедуре setup()).

Viator
Offline
Зарегистрирован: 18.01.2019

Мы, конечно, вернёмся к циклу опроса, но прежде, например, можем сообщить что-нибудь компьютеру...

VladimirTsibrov
Offline
Зарегистрирован: 05.03.2019

И все же я не вижу необходмости в wdt. Ждете внешний сигнал? - задействуйте прерывания. А в свободное время общайтесь с компьютером. Рассматривали такой вариант?

 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

ширина шины данных какова - раз, строб отдельная линия? - два, может проще через прерывание ловить строб и выполнять опрос шины данных?

Viator
Offline
Зарегистрирован: 18.01.2019

wdrakula пишет:

При подключенном USB с поднятым CDC драйвером на стороне хоста (сиречь "открытым монитором" ;) ), каждое прерываение USB, а хост их рождает регулярно, проверяя "жив ли пациент", производит ресет таймера вочдога. Если это тебе мешает - меняй логику программы или выводи диагностику не через USB.

Выходит, прерывания от USB начинают поступать, когда я запускаю терминал? А при выходе из терминала прерывания будут продолжаться? Ардуна-то и после закрытия терминала продолжает работать так, будто сторожевой таймер отключился...

Viator
Offline
Зарегистрирован: 18.01.2019

ua6em пишет:

ширина шины данных какова - раз, строб отдельная линия? - два, может проще через прерывание ловить строб и выполнять опрос шины данных?

Шина данных - 4 разряда.

На самом деле стробов - 10 линий (выше я несколько упростил задачу), но мы всегда знаем, какую линию опрашивать, и на другие не обращаем внимания. Прерыванием опрашивать дольше, чем программным опросом, да и десять источников прерываний, кажется, не осуществить...

VladimirTsibrov
Offline
Зарегистрирован: 05.03.2019

wdrakula пишет:

При подключенном USB с поднятым CDC драйвером на стороне хоста (сиречь "открытым монитором" ;) ), каждое прерываение USB, а хост их рождает регулярно, проверяя "жив ли пациент", производит ресет таймера вочдога. Если это тебе мешает - меняй логику программы или выводи диагностику не через USB.

Не в курсе дел CDC и хоста, может там и есть прерывания, но о каком сбросе WDT идет речь?

b707
Offline
Зарегистрирован: 26.05.2017

Viator пишет:

Строб короткий, и кроме проверки его состояния, в цикле ничего сделать не удаётся. Если строб появился - выход на продолжение программы, если нет - выход только по прерыванию.

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

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

VladimirTsibrov пишет:

wdrakula пишет:

При подключенном USB с поднятым CDC драйвером на стороне хоста (сиречь "открытым монитором" ;) ), каждое прерываение USB, а хост их рождает регулярно, проверяя "жив ли пациент", производит ресет таймера вочдога. Если это тебе мешает - меняй логику программы или выводи диагностику не через USB.

Не в курсе дел CDC и хоста, может там и есть прерывания, но о каком сбросе WDT идет речь?

wdt_reset();

Это функция такая ;)). Она использована в CDC.cpp в CDC_Setup(), которая вызывается  ...и так далее... в итоге в ISR(USB_COM_vect). Авторы взводят свой таймер на 120мс, но от этого ресетится сам вочдог таймер, так как в контроллере он один. Настройки они потом возвращают, а толку то? Все ж исходники открыты - сиди-изучай-радуйся! ;)))

Viator
Offline
Зарегистрирован: 18.01.2019

b707 пишет:

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



void loop() {

  register uint8_t result;
           uint8_t c1;

................

  __asm__ __volatile__ (
  "M1:           sbic %[inportb], 1"    "\n\t" // Опрос строба
                "rjmp M1"               "\n\t"
                "in %[reg], %[inportd]" "\n\t"    // Ввод данных
     :          [reg]     "=r" (result)
     :          [inportb] "I" (_SFR_IO_ADDR(PINB)),
                [inportd] "I" (_SFR_IO_ADDR(PIND))
                        );
  c1 = result; // Запоминаем данные

................

}

 

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

Проблема возникает при использовании Serial, так?

А Вы не пробовали не насиловать его пины? Если убрать строки №№21-22, ничего не меняется?

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

у ардуины прерывание аппаратное, не может оно не ловить, там же триггер взведён

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

Может не доходить до него.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

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

Может не доходить до него.

то-есть аппаратное прерывание реально может не отработать?

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

Ну, например, если МК сам по себе перегружается каждую секунду, как у него может отработать 8-секундный вочдог?

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

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

Ну, например, если МК сам по себе перегружается каждую секунду, как у него может отработать 8-секундный вочдог?

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

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

Ой, да мы тогда вообще о разном. Я даже не знаю о каком стробе речь :(((

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

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

Ой, да мы тогда вообще о разном. Я даже не знаю о каком стробе речь :(((

Строки 9 и 10 его скетча, где он программно ловит строб, там всё равно поймать с длительностью лучше 0,1 микросекунды не удастся

Viator
Offline
Зарегистрирован: 18.01.2019

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

Проблема возникает при использовании Serial, так?

А Вы не пробовали не насиловать его пины? Если убрать строки №№21-22, ничего не меняется?

Не вполне понимаю вопрос. Вывод по оператору Serial происходит же через интерфейс USB,  и выводы 0 и 1 для этого не задействованы.

Проверить смогу только завтра.

b707
Offline
Зарегистрирован: 26.05.2017

Viator пишет:

Не вполне понимаю вопрос. Вывод по оператору Serial происходит же через интерфейс USB,  и выводы 0 и 1 для этого не задействованы.

на МК Атмега нет интерфейса USB. Он делается сторонней микросхемой - преобразователем, выводы которой подключены к ногам 0 и 1 МК. Так что можно сказать. что USB и 0 и 1 - это одно и то же.

Green
Offline
Зарегистрирован: 01.10.2015

У Микро есть - там ATmega32u4.

b707
Offline
Зарегистрирован: 26.05.2017

Green пишет:

У Микро есть - там ATmega32u4.

ну значит не угадал

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

b707 пишет:

Green пишет:

У Микро есть - там ATmega32u4.

ну значит не угадал

Дракула просто так постил разве )))

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

Viator пишет:
Вывод по оператору Serial происходит же через интерфейс USB,  и выводы 0 и 1 для этого не задействованы.

Могу, конечно, ошибаться, т.к. микры под рукой нет, но судя вот по этой схеме, как раз задействованы. USB работает черезе пины контроллера 3 и 4, они же D1 и D0, они же TX и RX и они же D- и D+ для USB. Т.е. если эта схема верна, то пины 0 и 1 как раз используются в полный рост.

 

VladimirTsibrov
Offline
Зарегистрирован: 05.03.2019

Viator пишет:

Шина данных - 4 разряда.

На самом деле стробов - 10 линий (выше я несколько упростил задачу), но мы всегда знаем, какую линию опрашивать, и на другие не обращаем внимания. Прерыванием опрашивать дольше, чем программным опросом, да и десять источников прерываний, кажется, не осуществить...

Хотел было сказать, что двух прерываний PCINT хватит для отслеживания 10 линий, но, блин, у вас Micro. У нее один PCINT. Выбор этой ардуинки чем-то обоснован?

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

И я все еще не понимаю назначения wdt. Из-за короткого строба замутили цикл опроса на ассемблере,чтобы не пропустить данные. И вдруг на тебе, сбрасываем МК каждые N секунд. 

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

VladimirTsibrov пишет:

Выбор этой ардуинки чем-то обоснован?

Дак в первом же посте: "Имеется плата Arduino Pro Micro".

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

VladimirTsibrov пишет:

Viator пишет:

Шина данных - 4 разряда.

На самом деле стробов - 10 линий (выше я несколько упростил задачу), но мы всегда знаем, какую линию опрашивать, и на другие не обращаем внимания. Прерыванием опрашивать дольше, чем программным опросом, да и десять источников прерываний, кажется, не осуществить...

Хотел было сказать, что двух прерываний PCINT хватит для отслеживания 10 линий, но, блин, у вас Micro. У нее один PCINT. Выбор этой ардуинки чем-то обоснован?

НЕА! У неё 4 INT и 8 PCINT
 

VladimirTsibrov
Offline
Зарегистрирован: 05.03.2019

ua6em пишет:

НЕА! У неё 4 INT и 8 PCINT

Я о том, что прерывание PCINT одно, а источников-то 8, верно. Всё ж не 10. Делать часть на INT, часть на PCINT уже различная обработка получается, хотелось бы универсально.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

VladimirTsibrov пишет:

ua6em пишет:

НЕА! У неё 4 INT и 8 PCINT

Я о том, что прерывание PCINT одно, а источников-то 8, верно. Всё ж не 10. Делать часть на INT, часть на PCINT уже различная обработка получается, хотелось бы универсально.

так у него решено с обработкой с какой из 10 линий приходит строб, вроде как...
Я тоже за аппаратное решение средствами INT

VladimirTsibrov
Offline
Зарегистрирован: 05.03.2019

sadman41 пишет:

VladimirTsibrov пишет:

Выбор этой ардуинки чем-то обоснован?

Дак в первом же посте: "Имеется плата Arduino Pro Micro".

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

Я бы при наличии той же УНО использовал все-таки ее из-за трех прерываний PCINT.

Viator
Offline
Зарегистрирован: 18.01.2019

VladimirTsibrov пишет:

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

Других плат нет. Pro Micro показалась на первый взгляд подходящей для данной задачи. В  одном флаконе тебе и микроконтроллер, и питание, и интерфейс USB, и "облегчённое" программирование... Только корпус приделать да разъём подпаять. Выходит не всё так просто...

P.S. А может знает кто верный способ выйти из прерывания не в точку вызова, а на произвольно заданный адрес? Как вариант - на начало программы. Тогда можно было бы выходить из бесконечного цикла по таймеру. Или воэложить проверку таймаута на компьютер, принимающий данные, и при отсутствии таковых пусть он пошлёт ардуине какой-нибудь символ, отчего возникнет прерывание и будут выполнены действия по приведению устройств в исходное состояние...

(Мечтательно...) Вот был, к примеру, в фортране оператор RETURN m - возврат из подпрограммы на метку m...

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Это по нашему, создать проблему и героически её преодолевать )))

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

Viator пишет:

(Мечтательно...) Вот был, к примеру, в фортране оператор RETURN m - возврат из подпрограммы на метку m...

Здесь есть почти полный аналог, только ... из прерывания ... надеюсь, Вы знаете, что делаете, и знаете, как это правильно делать. Гуглите по словам setjmp и longjmp.

Вы заметили мой пост #37? Проверили?

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

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

Viator пишет:
Вывод по оператору Serial происходит же через интерфейс USB,  и выводы 0 и 1 для этого не задействованы.

Могу, конечно, ошибаться, т.к. микры под рукой нет, но судя вот по этой схеме, как раз задействованы. USB работает черезе пины контроллера 3 и 4, они же D1 и D0, они же TX и RX и они же D- и D+ для USB. Т.е. если эта схема верна, то пины 0 и 1 как раз используются в полный рост.

 

Женя! Это не так. D0 и D1 это контакты 20 и 21 чипа. Ты, возможно, путаешь с 328ым чипом. У 32U4 usb - совершенно отдельные пины никак не связанные с UART. На общие контакты платы они отдельно от разъема USB не выводятся.

Viator
Offline
Зарегистрирован: 18.01.2019

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

Вы заметили мой пост #37? Проверили?

Проверил - осталось как прежде.

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

wdrakula пишет:

Женя! Ты, возможно, путаешь

Вполне вероятно, я сразу предупредил, что могу ошибаться.

А что не так со схемой, на которую я ссылаюсь? С этого сайта? Я её неверно прочитал или она неверна?

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

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

wdrakula пишет:

Женя! Ты, возможно, путаешь

Вполне вероятно, я сразу предупредил, что могу ошибаться.

А что не так со схемой, на которую я ссылаюсь? С этого сайта? Я её неверно прочитал или она неверна?

не так прочитал ;)) она верна... не расстраивайся!