Борьба с наносекундными помехами Ардуино Мега 2560

ВН
Offline
Зарегистрирован: 25.02.2016

Roman2344 пишет:
Хоть ответьте правильно ли я думаю. Кстати прерывания основные и дополнительные я настроил регистрами, не применяя функции аттач ..

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

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

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

Потом, сетап по идеалогии выпослняется перед стартом основной программы 1 раз, зайти на сетап это фактически рестарт проца, какой смысл в таком прерывании, если это только не прерывание по вдт - непонятно.

Roman2344
Offline
Зарегистрирован: 09.09.2015

Прерывания разрешены в сетапе, регистрами настроенны на срабатывание по заднему фронту, вот только нет обработчиков прерываний. Идея такая сработал датчик с 1 в 0 потом прерывание которое перебрасывает в сетап, в сетапе идёт проверка состояния датчика и если 0 то выполняется бесконечный цикл вайл.

Roman2344
Offline
Зарегистрирован: 09.09.2015

Для дополнительных прерываний у меня тоже нету обработчиков прерываний на дополнительном у меня висит кнопка пуск-стоп ( кнопка с фиксацией)мне тоже создать пустой обработчик прерываний который сделает переход в сетап?

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

По умолчанию все прерывания wiring выстваляет на вектор _bad_interrupt(), который представляет из себя ровно одну команду: rti - возврат из процедуры обработчика прерывания. Так что, что там и какими регистрами "настроил" автор в сетапе, да ещё и без назначения обработчиков .. нипанятна.

Пока что (без кода) сумбурные разъяснения автора указывают только на то, что он что-то явно накуролесил в программе. Пока не разберется чего он (ли сам) там накуролесил и не исправит прогу .. двигаться далее и выискивать "пришельцев из розетки в 40см от платы" - думаю бесполезно.

ВН
Offline
Зарегистрирован: 25.02.2016

Roman2344 пишет:
Идея такая сработал датчик с 1 в 0 потом прерывание которое перебрасывает в сетап, в сетапе идёт проверка состояния датчика и если 0 то выполняется бесконечный цикл вайл.

Жаль что нет идеи почитать, что такое сетап, и как работают прерывания ....

 

Roman2344
Offline
Зарегистрирован: 09.09.2015

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


#include <memorysaver.h>
#include <UTFT.h>
UTFT myGLCD(ILI9486,38,39,40,41);

extern uint8_t BigFont[];//переменная размера шрифта
extern uint8_t SmallFont[];


#include <SPI.h>

#include <Wire.h>
#include <dht11.h> // Добавляем библиотеку DHT11
dht11 DHT;// Объявление переменной класса dht11
#define DHT11_PIN 10// Датчик DHT11 подключен к цифровому пину номер 4


long loopTime = 440000; // 7=7,5минут
long loopTime2 = 60000; // 1мин.
void _PCINT9Enable() {
    PCMSK1 |= _BV(PCINT9);
    PCICR  |= _BV(PCIE1);
}

void _PCINT10Enable() {
    PCMSK1 |= _BV(PCINT10);
    PCICR  |= _BV(PCIE1);
}


int zaliv = 14;//PCINT10
int razrab = 15;//PCINT9



void int0Control (uint8_t mode, bool enable){
    EIMSK &= ~ (1 >> INT0);                   
     
EICRA = _BV(ISC10);// по заднему фронту
    if (enable)
      EIMSK = _BV(INT0);                   // Разрешить прерывание
}






void setup() {
  analogReference(INTERNAL2V56);
delay(2000);
_PCINT9Enable();// разрешение дополнительных прерываний
_PCINT10Enable();
interrupts();// разрешение основных прерываний
if(digitalRead(razrab)==0){return;}// выполняем одно действие и переходим в Loop 
  
if(digitalRead(razrab)==1){return;}// выполняем сразу переход в Loop
  
}
}

void loop() {
  
  if ( digitalRead (razrab)!= 0){
    delay(30);
  while(i < 1) // выполняем действие один раз
    {
      unsigned long currentMillis = millis();
  while(millis()-currentMillis<=loopTime)// выполняем действие 7,5минут
  {
}
while(millis()-currentMillis<=loopTime)// выполняем действие 1минуту
}
      i++;
}
return;
}
 if ( digitalRead (razrab)!= 0){
    delay(30);
    //выполняем действие 
 
}

else if(digitalRead(razrab)==0){
  //иначе выполняем другое действие 
}
}
ISR(PCINT9_vect) // после задержки в обработчике прерываний происходит переход в Сетап

{static unsigned long millis_prev;
  if(millis()-100 > millis_prev)  
  millis_prev = millis();  // задержка
}


ISR(PCINT10_vect) // x - номер прерывания

{static unsigned long millis_prev;
  if(millis()-100 > millis_prev)  
  millis_prev = millis();  
}

ISR(INT0_vect)
{static unsigned long millis_prev;
  if(millis()-100 > millis_prev)  
  millis_prev = millis();  
   
}

 

Roman2344
Offline
Зарегистрирован: 09.09.2015

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

trembo
trembo аватар
Offline
Зарегистрирован: 08.04.2011

В середине этой странички прочтите что происходит с millis() во время прерывания
http://arduino.ru/Reference/AttachInterrupt

Roman2344
Offline
Зарегистрирован: 09.09.2015

Да я читал, но на форумах утверждают что работает. Мне впринципе задержка от дребезга нужна для одной кнопки(да она применяется редко, и задержку думаю можно сделать и в функции if обычным delay(30);), остальные обработчики прерываний оставить пустыми что ли? Как правильно сделать прерывания? 

ВН
Offline
Зарегистрирован: 25.02.2016

скорее тут надо смотреть область видимости переменной объявленой как static в какой-то функции.

т.е. насколько понимаю, три вызова  static unsigned long millis_prev;

порождают три независимых переменных, хотя Roman2344 похоже считает, что  работает с одной.

т.е. объявление millis_prev следует сделать 1 раз, вне тела прерываний.

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

 

 

Roman2344
Offline
Зарегистрирован: 09.09.2015

Основная задача мне нужно что бы обработчик прерываний меня перекидывал либо в сетап, либо в начало void loop.

Roman2344
Offline
Зарегистрирован: 09.09.2015

Сделал так тоже самое


#include <memorysaver.h>
#include <UTFT.h>
UTFT myGLCD(ILI9486,38,39,40,41);

extern uint8_t BigFont[];//переменная размера шрифта
extern uint8_t SmallFont[];


#include <SPI.h>

#include <Wire.h>
#include <dht11.h> // Добавляем библиотеку DHT11
dht11 DHT;// Объявление переменной класса dht11
#define DHT11_PIN 10// Датчик DHT11 подключен к цифровому пину номер 4
#define INT0_SENSE_FALLING_EDGE  2        // Прерывание по фронту на спад (когда 1 переходит в 0)

long loopTime = 440000; // 7=7,5минут
long loopTime2 = 60000; // 1мин.
void _PCINT9Enable() {
    PCMSK1 |= _BV(PCINT9);
    PCICR  |= _BV(PCIE1);
}

void _PCINT10Enable() {
    PCMSK1 |= _BV(PCINT10);
    PCICR  |= _BV(PCIE1);
}


int zaliv = 14;//PCINT10
int razrab = 15;//PCINT9



void int0Control (uint8_t mode, bool enable){
    EIMSK &= ~ (1 >> INT0);                   
     
EICRA = _BV(ISC10);// по заднему фронту
    if (enable)
      EIMSK = _BV(INT0);                   // Разрешить прерывание
}






void setup() {
  analogReference(INTERNAL2V56);
delay(2000);
_PCINT9Enable();// разрешение дополнительных прерываний
_PCINT10Enable();
 int0Control(INT0_SENSE_FALLING_EDGE, true);    // Разрешить прерывание по фронту на спад
interrupts();// разрешение основных прерываний
if(digitalRead(razrab)==0){return;}// выполняем одно действие и переходим в Loop 
  
if(digitalRead(razrab)==1){return;}// выполняем сразу переход в Loop
  
}
}

void loop() {
  
  if ( digitalRead (razrab)!= 0){
    delay(30);
  while(i < 1) // выполняем действие один раз
    {
      unsigned long currentMillis = millis();
  while(millis()-currentMillis<=loopTime)// выполняем действие 7,5минут
  {
}
while(millis()-currentMillis<=loopTime)// выполняем действие 1минуту
}
      i++;
}
return;
}
 if ( digitalRead (razrab)!= 0){
    delay(30);
    //выполняем действие 
 
}

else if(digitalRead(razrab)==0){
  //иначе выполняем другое действие 
}
}
ISR(INT0_vect)
{static unsigned long millis_prev1;
  if(millis()-100 > millis_prev1)  
  millis_prev1 = millis();  
   
}

ISR(PCINT9_vect) // после задержки в обработчике прерываний происходит переход в Сетап

{static unsigned long millis_prev2;
  if(millis()-100 > millis_prev2)  
  millis_prev2 = millis();  // задержка
}


ISR(PCINT10_vect) // x - номер прерывания

{static unsigned long millis_prev3;
  if(millis()-100 > millis_prev3)  
  millis_prev3 = millis();  
}

 

ВН
Offline
Зарегистрирован: 25.02.2016

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

и реально нужно 3 разных millis_prev ?

Если нужно после выполнения прерывания совершить куда-то переход, введи какой-то флаг и устанавливай его внутри прерывания, а в осн цикле проверяй и делай переход куда надо, если флаг установлен.

Roman2344
Offline
Зарегистрирован: 09.09.2015

Сделал так теперь использую только основные внешние прерывания, без дополнительных.

Питаю от БП ничего не перезагружается, осталось понять как сделать переход в начало функции loop после обработчика прерываний void pusk


#include <memorysaver.h>
#include <UTFT.h>
UTFT myGLCD(ILI9486,38,39,40,41);

extern uint8_t BigFont[];//переменная размера шрифта
extern uint8_t SmallFont[];


#include <SPI.h>

#include <Wire.h>
#include <dht11.h> // Добавляем библиотеку DHT11
dht11 DHT;// Объявление переменной класса dht11
#define DHT11_PIN 10// Датчик DHT11 подключен к цифровому пину номер 4
#define INT0_SENSE_FALLING_EDGE  2        // Прерывание по фронту на спад (когда 1 переходит в 0)

long loopTime = 440000; // 7=7,5минут
long loopTime2 = 60000; // 1мин.



int zaliv = 21;//INT3
int razrab = 3;//INT2
int utechka = 2;//INT0






void setup() {
  analogReference(INTERNAL2V56);
delay(2000);
attachInterrupt(0, datchik, FALLING);
attachInterrupt(1, pusk, CHANGE);
attachInterrupt(2,zaliv2, CHANGE);
if(digitalRead(razrab)==0){return;}// выполняем одно действие и переходим в Loop 
  
if(digitalRead(razrab)==1){return;}// выполняем сразу переход в Loop
  
}
}

void loop() {
  
  if ( digitalRead (razrab)!= 0){
    delay(30);
  while(i < 1) // выполняем действие один раз
    {
      unsigned long currentMillis = millis();
  while(millis()-currentMillis<=loopTime)// выполняем действие 7,5минут
  {
}
while(millis()-currentMillis<=loopTime)// выполняем действие 1минуту
}
      i++;
}
return;
}
 if ( digitalRead (razrab)!= 0){
    delay(30);
    //выполняем действие 
 
}

else if(digitalRead(razrab)==0){
  //иначе выполняем другое действие 
}
}




void datchik()
{static unsigned long millis_prev1;
  if(millis()-100 > millis_prev1)  
  millis_prev1 = millis();  
   
}
void pusk()
{static unsigned long millis_prev2;
  if(millis()-100 > millis_prev2)  
  millis_prev2 = millis();  
   
}
void zaliv2()
{static unsigned long millis_prev3;
  if(millis()-100 > millis_prev3)  
  millis_prev3 = millis();  
   
}

 

Roman2344
Offline
Зарегистрирован: 09.09.2015

А можно переход из обработчика прерываний сделать goto и поставить метку в начале void loop?

ВН
Offline
Зарегистрирован: 25.02.2016

Roman2344 пишет:
А можно переход из обработчика прерываний сделать goto и поставить метку в начале void loop? 
хм ... это не вариант, поскольку ты вывалишься в основной цикл, то постепенно возникнет множество вызванных и не закрытых прерываний, а этому есть предел.

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

да и еще вступает в действие это ограничение

"Внутри функции обработки прерывания не работает delay(), значения возвращаемые millis() не изменяются"

 

Наверно можно попробовать, как ты первоначально хотел: сдеть goto на сетап или вызвать сетап в конце обработки  прерывания. Вроде как в этом случае все флаги должны бы быть сброшены в исходное состояние и указатель поставлен в начало стека,  прерывание сбрасывается по дефолту.

Похоже на партизанщину, но возможно такой вариант и пройдет. 

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

1. Код, который вы привели, как понимаю "сильно урезан", ибо в таком виде он не способен даже скомпиляться, поскольку после функции setup() стоит аж сразу 2 закрывающие фигурные скобки .. да и остальной код мягко говоря "ни о чем".

Строка 50 последнего примера всегда выдаст "истину", поскольку значение currenMillis присваивается непосредственно стркой выше .. да и сам цикл - пуст (строки 51,52) и будет редуцирован оптимизатором как избыточный.

2. Поскольку читать описание wiring вам явно "в лом", то напомню что функция setup() предназначена ИСКЛЮЧИТЕЛЬНО для первичной настройки выводов, переменных и прочих условий работы программы. А функция loop() предназначена для выполнение постоянных повторяющихся действий ПОСЛЕ таковой настройки. Соответственно ваш вопрос, хотя и имеет положительное решение, тем не менее "странен" и, как понимаю, из-за нежелания читать документацию на платформу и её библиотеки.

3. Поскольку приведенный кусок кода очевидно неграмотен (имеет использование неустановленных переменных, что вам уже заметили), то смею предположить, что и остальной код ровно такой же. А стало быть, искать ваших "пришельцев" надо в первую очередь не из розетки, а в самом коде программы.

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

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Не стоит предлагать неграмотных решений. Вывал из обработчика прерывания в setup(), следуюя логике wiring - это желание "странного" и не предполагается от слова "никак", ибо незачем.

Roman2344
Offline
Зарегистрирован: 09.09.2015

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