i2c display и прерывания.

BorisU
Offline
Зарегистрирован: 11.09.2015

Здравствуйте, уважаемые специалисты. Помогите разобраться с проблемой. Есть желание измерять мгновенное значение проходящей в трубе жидкости. Для этого приобретен прибор http://ru.aliexpress.com/item/1-x-1-30L-min-1-75MPa-Water-Flow-Sensor-Flowmeter-Hall-Flow-Water-Sensor-New/2045383642.html?spm=2114.03020208.3.29.9p7lIN&ws_ab_test=201407_2,201444_5,201409_3 К нем есть стандартный скетч с выводом данных через Serial порт.

[code]
// reading liquid flow rate using Arduino and Water Flow sensor.
volatile int Fan;//measuring the rising edges of the signal
int Calc;
int hallsensor = 2;//The pin location of the sensor
 
void rpm()//this is the function of that the interupt calls
{
  Fan++;
}
 
void setup() {
  pinMode(hallsensor, INPUT);
  Serial.begin(9600);
  attachInterrupt(0, rpm, RISING);
}
 
void loop() {
  Fan=0;
  sei();
  delay(1000);
  cli();
  Calc = (Fan*60/5.5);//(puls frequency x 60)/5.5Q = flow rate in L/hour
  Serial.print (Calc, DEC);
  Serial.print (" L/hour\r\n"); //Prints "L/hour" and returnes a new line
}
 
[/code]
Все работает. Но хотелось бы вывести результат на lcd дисплей. Есть под рукой lcd 20 на 4 с интерфейсом i2c. Берем скетч из примеров, делаем микс из двух получаем:
[code]
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
LiquidCrystal_I2C lcd(0x27,20,4);
// reading liquid flow rate using Arduino and Water Flow sensor.
volatile int Fan;//measuring the rising edges of the signal
int Calc;
int hallsensor = 2;//The pin location of the sensor
 
void rpm()//this is the function of that the interupt calls
{
  Fan++;
}
 
void setup() {
  pinMode(hallsensor, INPUT);
  attachInterrupt(0, rpm, RISING);
  lcd.init();
  lcd.backlight();
}
 
void loop() {
  Fan=0;
  sei();
  delay(1000);
  cli();
  Calc = (Fan*60/5.5);
  //lcd.clear;
  lcd.print (Calc, DEC);
}
 
[/code]
Но данный код не работает. Если исключить из кода строки 
sei();
delay(1000);
cli();
а переменной Fan присвоить значение (например 10) то на экране появляется значение, полученное при вычислении (при Fan=10 получим 109, что есть правильно).
Подскажите, в чем проблема.
Заранее благодарю.
 
dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

BorisU, этот ваш скетч для замера просто как пример работы, никто в здравом уме такие программы не использует. Наиболее просто можно обойти delay по аналогии со светодиодом http://arduino.ru/tutorials/BlinkWithoutDelay

PS: вообще-то уберите cli() наверное и так заработает.

BorisU
Offline
Зарегистрирован: 11.09.2015

dimax, не заработало. Индикации как не было так и нет.

По поводу cli(). Если убрать это убрать, то не понятно, как программа будет работать. Логика простая. Есть датчик Холла. Нам нужно знать сколько импульсов пройдет в единицу времени. Для этого мы ставим sei() - enable interrupt, delay(1000) - считаем количество импульсов за секунду, cli() - disable interrupt. Переменная Fan больше не меняется и можно проводить вычисления. Если убрать cli(), то ничего посчитать будет нельзя, так как не будет не ясно за какое время прошло n импульсов. Как-то так.

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

BorisU, нет, разрешение и запрещение прерываний тут фактически не на что не влияют.  Если ставить cli(),  то с  этого момента и до sei() переменная Fan не инкременируется. Если не стоит, то переменная конечно инкременируется, но перед паузой всё равно обнуляется. Проверьте. С LCD без cli работать должно, попробуйте после Lcd.print небольшую паузу поставить. А лучше конечно переделать всё, что б небыло секундной паузы.

PS: Вот, начертил,  пробуйте:

#include <LiquidCrystal_I2C.h>
#include <Wire.h>
LiquidCrystal_I2C lcd(0x27,20,4);
volatile uint16_t Fan;//measuring the rising edges of the signal
uint16_t Calc;
byte hallsensor=2;//The pin location of the sensor
void rpm() { Fan++;}
ISR (TIMER1_OVF_vect){Calc = (Fan*60/5.5); Fan=0; }

void setup() {
  pinMode(hallsensor, INPUT);
  //Serial.begin(9600);
  attachInterrupt(0, rpm, RISING);
  TCCR1A=(1<<WGM11); //режим14 FAST PWM 
  TCCR1B=(1<<CS12)|(1<<WGM13)|(1<<WGM12); //делить частоту CPU на 256
  ICR1= (F_CPU/256)-1;  // (16000000MHz /div256) -1 = 1 раз в секунду
  TIMSK1=(1<<TOIE1); //разрешить прерывание
}

void loop() {
static uint16_t n;
if (n!=Calc){n=Calc;
  lcd.print (Calc);
  // Serial.println (Calc);
  }
}

Здесь время считает таймер, каждую секунду выходит в прерывание, делает подсчёт, обнуляет Fan, и начинает сначала. В лупе выводит данные только если есть изменения. Никаких delay :-)

inspiritus
Offline
Зарегистрирован: 17.12.2012

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

Конкатенация не помогает, включайте понимание.

Dimax Вы издеваетесь? К Вам с букварём, а Вы с алгеброй :)

BorisU
Offline
Зарегистрирован: 11.09.2015

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

По сути проблемы. Она, проблема, заключается в том, что изначально значение переменной Cacl выводится на монитор последовательного порта, но не выводится на lcd. Кусок кода с sei and cli я убирал, что бы убедиться, что проблем с lcd как таковым нет. Код выше, я уверен, более правильный с точки зрения науки, но он тоже не работает. Информация не выводиться ни на lcd, ни на монитор порта. К сожалению. 

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

BorisU, а какая у вас плата? Скетч, который я дал -это готовая рабочая "шапка" для atmega328, я в него просто ваши исходные данные вставил. Не работать он не может)

BorisU
Offline
Зарегистрирован: 11.09.2015

Я тестил на меге 2560 r3. Вся проблема в выводе данных на дисплей. Дисплей девственно чист. Я, как уже ясно, еще собаку не съел на этом деле, и поэтому могу задавать глупые вопросы. Я подумал, нет ли связи между интерфейсом I2C и прерываниями?

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

BorisU, в обработчике I2C есть прерывание, но оно не используется в режиме мастер по-моему. Так что взаимосвязи нет, разбирайтесь, что делаете не так. Попробуйте в lcd.print вывести просто текст lcd.print("test"); например. Кстати посмотрел, мой скетч по идее совместим с мегой2560, так что должен работать. Разкомментируйте строчки,  выведите в serial для проверки.

BorisU
Offline
Зарегистрирован: 11.09.2015

dimax, что бы все было ясно и понятно. Я взял "неправильный" скетч. Закомментил sei() и cli(). Присвоил переменной Calc=10. Загрузил в Мегу. Дисплей показал 109, что является правильным ответом. Удалил почти все, кроме библиотек. Вставил Ваш код. Загрузил в Мегу. Дисплей не показывает ничего. Закомментил все что касается lcd и раскомментил Serial. Загрузил в Мегу. Монитор порта не показывает ничего.

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

BorisU, когда пробывали в сериал выводить - то 3 и 23 строку закомментировали? Если lcd зависнет, то он заблокирует loop

BorisU
Offline
Зарегистрирован: 11.09.2015

dimax, да закомментировал все, что относиться к lcd включая библиотеки. Результат - показаний нет.

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

BorisU, не знаю что вам посоветовать. Попробуйте на уно.  Я вчера проверил скетч, подключил вместо счётчика энкодер. Покрутил - как и следовало ожидать всё работает. Меги2560 у меня нет, но разницы по идее быть не должно.

PS: заметил ещё любопытную вещь: вы используете прерывание 0   attachInterrupt(0, rpm, RISING); а пин у вас указан 2. Но этот пин для Уно, у меги2560  INT0 на 21-ой ардуиновской ноге. Но тогда непонятно как у вас работал первый вариант без LCD.

BorisU
Offline
Зарегистрирован: 11.09.2015

dimax, большое спасибо за помощь. Я тестил на нано, но результат тоже отрицательный. Думаю нужно задать вопрос в аппаратной ветке. А за скетч спасибо еще раз. Я его разобрал уже процентов на 80. Там все не так сложно, но нужно еще некоторые вопросы синтаксиса разобрать.

nevkon
Offline
Зарегистрирован: 20.01.2015

Впервые вижу такое объявление экрана ( LiquidCrystal_I2C lcd(0x27,20,4); ).

Где lcd.begin?

BorisU
Offline
Зарегистрирован: 11.09.2015

dimax, есть новость. Я установил на другой компьютер среду версию 1.6.3 (на родном версия 1.5.7) и протестил. На мониторе порта все работает, на lcd нет. Результат - lcd не хочет работать ни при каких условиях. Значит нужно спрашивать о совместимости железа. 

BorisU
Offline
Зарегистрирован: 11.09.2015

Это объявление работает. Все зависит от библиотеки, как я понимаю. Кстати, с этой библиотекой нужно lcd.init вместо lcd.begin. Экран работает с этой библиотекой.

nevkon
Offline
Зарегистрирован: 20.01.2015

А если экран цеплять не по i2c, то работает?

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

BorisU пишет:

На мониторе порта все работает, на lcd нет. Результат - lcd не хочет работать ни при каких условиях. Значит нужно спрашивать о совместимости железа. 

Попробуйте другую библиотеку LCD, возможно эта просто кривая или со свежими версиями IDE не совместима. У меня кстати помимо новой есть дежурная ардуино IDE 1.0.5 , и всегда проверяю  на ней, если есть подозрения на несовместимость.

BorisU
Offline
Зарегистрирован: 11.09.2015

Да, я согласен, нужно другую библиотеку потестить. А экрана без I2C у меня нет, а выпаять - не так просто. Ног много можно перегреть, отслоиться плата. Напишу как найду подходящую библиотеку.

Radjah
Offline
Зарегистрирован: 06.08.2014

У меня все китайские так запускались. Либа

#include <Wire.h>
#include <LCD.h>
#include <LiquidCrystal_I2C.h>


#define LCD_I2C_ADDR    0x27
#define BACKLIGHT     3
#define LCD_EN  2
#define LCD_RW  1
#define LCD_RS  0
#define LCD_D4  4
#define LCD_D5  5
#define LCD_D6  6
#define LCD_D7  7

LiquidCrystal_I2C       lcd(LCD_I2C_ADDR,LCD_EN,LCD_RW,LCD_RS,LCD_D4,LCD_D5,LCD_D6,LCD_D7);

void setup() {
  lcd.begin(20,4);
  lcd.setBacklightPin(BACKLIGHT,POSITIVE);
  lcd.setBacklight(HIGH);
  lcd.clear();
}

 

Ujine
Offline
Зарегистрирован: 06.04.2017

Доброго аремени суток уважаемый ALL!

Есть проблема с работой дисплея 1602 подключенного к atmege 328 по i2c при обработке прерывания.

при попытке вывести сообщение на экран при обработке прерывания работа устройства замерзает.

вот текст проги

[code]
#include <Wire.h>;
#include <math.h>;
#include <LiquidCrystal_I2C.h>;

LiquidCrystal_I2C lcd(0x3F, 16, 2); // set the LCD address to 0x27 for a 16 chars and 2 line display


//======================================================================================================================
//    Переменные
//======================================================================================================================
float davlenie = 0;
float Hdav = 0.5;                     //Максимальное давление в системе, давление отключения насоса mPa
float Ldav = 0.3;                     //Минимальное давление в системе, давление включения насоса mPa
float Adav = 0.6;                     //Давление возникающее при аврии системы mPa
int water;                            //Уровень воды в колонне
int state = HIGH;
int pumpState = 7;                    // флаг состояния насоса
int tempState;                        // флаг состояния температуры




//======================================================================================================================
// кодируем дополнительные символы
//======================================================================================================================
byte degree[8] = // кодируем символ градуса
{
  B11100,
  B10100,
  B11100,
  B00000,
  B00000,
  B00000,
  B00000,
};
byte gradusnik[8] = // кодируем символ градусника
{
  B00100,
  B01010,
  B01010,
  B01110,
  B11111,
  B11111,
  B01110,
};


//======================================================================================================================


void setup()
{

  lcd.init();                                          // initialize the lcd
  lcd.init();
  lcd.backlight();

  lcd.print(" WATER  MAN 0.1 ");
  lcd.createChar(1, degree);                           // Создаем символ под номером 1
  lcd.createChar(2, gradusnik);                        // Создаем символ под номером 2
  lcd.setCursor(0, 1);
  for (int i = 0; i < 16; i++)
  {
    lcd.print("_");
    delay(200);
  }

  pinMode(13, OUTPUT);                                 //порт управления насосом
  pinMode(12, OUTPUT);                                 //порт индикатора аварии
  pinMode(11, OUTPUT);                                 //порт индикатора низкой температуры
  pinMode(10, OUTPUT);                                 //порт управления электромагнитным кдапаном
  pinMode(9, OUTPUT);                                  //порт управления водозависимым устройством
  pinMode(2, INPUT_PULLUP);                            //Порт аварийной кнопки

  pinMode(A0, INPUT) ;                                 //инициализируем датчик давления
  pinMode(A1, INPUT) ;                                 //инициализируем терморезистор в кесоне
  pinMode(A2, INPUT) ;                                 //инициализируем терморезистор в бойлерной
  pinMode(A3, INPUT) ;                                 //инициализируем датчик сухого хода

  delay (1000);
  lcd.clear();
  //digitalWrite(9, HIGH);
  attachInterrupt(0, Hend_Stop, LOW);                  //Вызов прерывания по нажатию кнопки STOP
}

//======================================================================================================================
// создаем метод для перевода показаний сенсора в градусы Цельсия
//======================================================================================================================
double Getterm(int RawADC) {
  double temp;
  temp = log(((10240000 / RawADC) - 10000));
  temp = 1 / (0.001129148 + (0.000234125 * temp) + (0.0000000876741 * temp * temp * temp));
  temp = temp - 273.15;
  return temp;
}
void loop() {

  water = analogRead(A3);                      // читаем датчик сухого хода
  davlenie = analogRead(A0);                   // читаем датчик давления в системе

  davlenie = map(davlenie, 531, 1023, 0, 85);  // приводим значения давления к читаемым
  davlenie = davlenie / 100;

  //======================================================================================================================
  //          Модуль управления насосом
  //======================================================================================================================

  if (water <= 100)
  {
    if ((Getterm(analogRead(A1))) >= 1 && (Getterm(analogRead(A2))) >= 1)
    {
      digitalWrite(10, LOW);
      digitalWrite(11, LOW);
      tempState = 1; //Флаг включения водозависимых устройств
      if (davlenie >= 0.6)
      {
        digitalWrite(13, LOW);
        //digitalWrite(9, LOW);
        pumpState = 1; //Флаг аварии
        digitalWrite(12, state);
        lcd.display();
        state = !state;
      }

      if (davlenie >= 0.5)
      {
        digitalWrite(13, LOW);
        digitalWrite(12, LOW);
        pumpState = 2; //Флаг насос остановлен
      }

      if (davlenie <= 0.3)
      {
        digitalWrite(13, HIGH);
        digitalWrite(12, LOW);
        pumpState = 3; //Флаг набор давления насос включен

      }
      if (davlenie <= 0.1)
      {
        digitalWrite(13, HIGH);
        digitalWrite(12, HIGH);
        pumpState = 4; //Флаг насос не запустился
        digitalWrite(12, state);
        state = !state;
      }

    }
    else
    {
      digitalWrite(13, LOW);
      digitalWrite(12, state);
      digitalWrite(9, LOW);
      digitalWrite(11, HIGH);
      if (davlenie >= 0)
      {
        digitalWrite(10, HIGH);
      }
      else
      {
        digitalWrite(10, LOW);
      }
      state = !state;
      pumpState = 5; //Флаг низкая температура запуск насоса не возможен, сливной клапан открыт, риск размораживания системы
      tempState = 0;
    }
  }
  else
  {
    //digitalWrite(13, LOW);
    digitalWrite(12, HIGH);
    state = !state;
    digitalWrite(9, LOW);
    pumpState = 6; //Флаг cухой ход, запуск насоса не возможен риск поломки насоса
  }


  //=====================================================================================================================
  //         Модуль управления дополнительным водозависимым оборудованием
  //=====================================================================================================================

  if (davlenie >= 0.25 && tempState == 1)
  {
    digitalWrite(9, HIGH);
  }
  else
  {
    digitalWrite(9, LOW);
  }

  pump_print(pumpState);
  delay(500);
}



void pump_print(byte pumpFlag)
{
  //====================================================================================================================
  //    Модуль вывода на экран верхней строки
  //====================================================================================================================
  if (pumpFlag != 5 || pumpFlag != 6)
  {
    lcd.setCursor(0, 0);
    lcd.print("\2");                                             // Выводим:Temperature:
    lcd.setCursor(1, 0);
    lcd.print (round(Getterm(analogRead(A1))));                  // Выводим: температуру
    lcd.print("\1");                                             // Выводим: *C
    lcd.setCursor(5, 0);
    lcd.print("\2");                                             // Выводим:Temperature:
    lcd.setCursor(6, 0);
    lcd.print("    ");
    lcd.setCursor(6, 0);
    lcd.print (round(Getterm(analogRead(A2))));                  // Выводим: температуру
    lcd.print("\1");                                             // Выводим: *C
    lcd.setCursor(10, 0);
    lcd.print("P");
    lcd.print(davlenie * 10);                                    // Выводим давление
    lcd.setCursor(14, 0);
    lcd.print("    ");
    lcd.setCursor(14, 0);
    lcd.print("aT");
  }
  //====================================================================================================================
  //    Модуль вывода на экран нижней строки
  //====================================================================================================================
  if (pumpFlag == 1)
  {
    lcd.setCursor(0, 1);
    lcd.print("  PUMP FAILURE  ");
    lcd.noDisplay();
    delay(500);
    lcd.display();
  }
  if (pumpFlag == 2)
  {
    lcd.setCursor(0, 1);
    lcd.print("THE PUMP IS STOP");
  }
  if (pumpFlag == 3)
  {
    lcd.setCursor(0, 1);
    lcd.print(" THE PUMP WORKS ");
  }
  if (pumpFlag == 4)
  {
    lcd.setCursor(0, 1);
    lcd.print("  PUMP NOT RUN  ");
    lcd.noDisplay();
    delay(500);
    lcd.display();
  }
  if (pumpFlag == 7)
  {
    lcd.setCursor(0, 1);
    lcd.print("  SYSTEM  TEST  ");
  }
  //====================================================================================================================
  //    Модуль вывода на экран аварийного состояния
  //====================================================================================================================

  if (pumpFlag == 5)
  {
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print(" SYSTEM HALTED! ");
    lcd.setCursor(0, 1);
    lcd.print("TEMPERATURE  LOW");
    lcd.noDisplay();
    delay(500);
    lcd.display();
  }
  if (pumpFlag == 6)
  {
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print(" SYSTEM HALTED! ");
    lcd.setCursor(0, 1);
    lcd.print("WATER LEWEL  LOW");
    lcd.noDisplay();
    delay(500);
    lcd.display();
  }
  pumpState = 0;
  pumpFlag = 0;
}


void Hend_Stop()
{
  digitalWrite(13, LOW);
  digitalWrite(12, HIGH);
  digitalWrite(9, LOW);
  davlenie = analogRead(A0);                   // читаем датчик давления в системе
  davlenie = map(davlenie, 531, 1023, 0, 85);  // приводим значения давления к читаемым
  davlenie = davlenie / 100;
  if (davlenie >= 0)
  {
    digitalWrite(10, HIGH);
  }
  else
  {
    digitalWrite(10, LOW);
  }
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.write(" SYSTEM HALTED! ");
  lcd.setCursor(0, 1);
  lcd.write("PRESS STOP");
  }
[/code]

подскажите как победить этот трабл.

сильно не пинайте ламера.

Ujine
Offline
Зарегистрирован: 06.04.2017

P.S. при коментировании строк обращения к экрану в обработчике прерывания все работает нормально.

sadman41
Онлайн
Зарегистрирован: 19.10.2016

Ну, значит какой вывод? Нефиг в ISR пихать все подряд.  Выставили там флаг и в главном цикле написали на LCD, если флаг выставлен.

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

Так и должно быть. Эта библиотека слишком медленно работает с экраном. Тут есть относительно скоростной драйвер, но и он шустрее 95-125мксек на символ не работает. Примерно 1.58-2.0 миллисекунды на строку в 16 символов - это "самое шустрое" что можно предложить. Чтобы работать неблокирующе с экраном надо преобразовать ваш код и библиотеку (или "шустрый" драйвер) так, чтобы пока экран занят отрисовкой можно было бы что-нибудь делать полезное.

В общем, сейчас немного занят, но в планы себе поставил.

Ujine
Offline
Зарегистрирован: 06.04.2017

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

DetSimen
DetSimen аватар
Онлайн
Зарегистрирован: 25.01.2017

вабрабоччике прерывания прерывания запрещены, а нутренний i2c работает на прерываниях. Дальше прадолжать?

vvadim
Offline
Зарегистрирован: 23.05.2012

и нафига вам здесь прерывания нужны....

Ujine
Offline
Зарегистрирован: 06.04.2017

Дело в том, что есть необходимость остановить выполнение, программы по нажатию аварийной кнопки, при этом должны сработать клапана аварийного сброса давления

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Ujine, похоже программировать через цифровой автомат запретили на территории РФ для новичков и остальных.

vvadim
Offline
Зарегистрирован: 23.05.2012

Ujine пишет:

Дело в том, что есть необходимость остановить выполнение, программы по нажатию аварийной кнопки, при этом должны сработать клапана аварийного сброса давления

 

и для этого без прерываний никак?

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

vvadim пишет:
и для этого без прерываний никак?
Конечно никак, если писать блокирующие куски. А потом выходить из блокировки по прерыванию. А когда надо прерывать обработчик прерывания, то выходит это. В общем учите программирование  через цифровой автомат . Это залог здоровых нервов при работе программы.

Logik
Offline
Зарегистрирован: 05.08.2014

Ешшо и прерывание по кнопке. Мрак безпросветный. Исходник сжечь. Новый писать после изучения фундаментальных трудов классиков.

save.l
Offline
Зарегистрирован: 03.12.2016

DetSimen пишет:

вабрабоччике прерывания прерывания запрещены, а нутренний i2c работает на прерываниях. Дальше прадолжать?

Уважаемые форумчане, подскажите, пожалуйста.

Работаю с несколькими устройствами по шине I2C (в частности lcd, eeprom, ds3231, mcp23017), плюс использую код для отправки сообщений в стороннее железо по протоколу wiegand26 :

         //собираем пакет       
          readerTmp[9] =  bitRead(c3, 3);
          //....
          readerTmp[24] =  bitRead(c3, 0);

        //бит нечетности 1-12
        byte bit1 = 0;
        for (byte b1 = 1; b1 <= 12; b1 ++) bit1 = bit1 + readerTmp[b1];
        if (bit1 % 2) readerTmp[0] = 1;
          else readerTmp[0] = 0;

        //бит четности 13-24
        byte bit2 = 0;
        for (byte b2 = 13; b2 <= 24; b2 ++) bit2 = bit2 + readerTmp[b2];
        if (bit2 % 2) readerTmp[25] = 0;
          else readerTmp[25] = 1;
       
        //отправка
        for (byte i = 0; i <= 25; i ++) {
         if(readerTmp[i] == 0){
           delay(2);
           digitalWrite(p_D0, LOW);
           delayMicroseconds(50);
           digitalWrite(p_D0, HIGH);
         }else{
              delay(2);
              digitalWrite(p_D1, LOW);
              delayMicroseconds(50);
              digitalWrite(p_D1, HIGH);
          }  
        }

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

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

save.l пишет:

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

Что-то не понятно где обработчик прерывания в вышеприведенном коде и как там светодиод управляется.

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

save.l
Offline
Зарегистрирован: 03.12.2016

asam пишет:

Что-то не понятно где обработчик прерывания в вышеприведенном коде и как там светодиод управляется.

в планах. спросил возможен ли такой подход, без подводных камней.

обработчик прерывания планирую такой:

volatile uint8_t  blink_mode = 0;

void timerIsr()
{
   static byte  blink_time = 0;
   static byte  blink_loop = 0;
     
   blink_time++; 
   if( blink_time > (4 * 5)){
        if( blink_mode & 1<<(blink_loop&0x07) ){
          mcp.digitalWrite(p_ledErr, HIGH); 
        } else {
            mcp.digitalWrite(p_ledErr, LOW);
          }
        blink_loop++; 
   }
   if( blink_time >= (4 * 7)){
      blink_time = 0;
      blink_loop = 0; 
   }

}

void setup() {
  //...
  Timer1.initialize(250000);  
  Timer1.attachInterrupt( timerIsr ); 
  //...
}

 

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

save.l пишет:

обработчик прерывания планирую такой:

volatile uint8_t  blink_mode = 0;

void timerIsr()
{

          mcp.digitalWrite(p_ledErr, HIGH); 

}

 

Так точно работать не будет. Безпроблемно в прерывании можно дергать только пины самой Ардуины. 

В данном случае, скорее всего, достаточно будет разрешить глобальные прерывание в начачале timerIsr(). Но этро при условии что Timer1 нигде больше не используется.

save.l
Offline
Зарегистрирован: 03.12.2016

asam пишет:

 Безпроблемно в прерывании можно дергать только пины самой Ардуины. 

спасибо, как раз есть 1 свободный пин