Зависает прерывание?
- Войдите на сайт для отправки комментариев
Сделал индикатор мощности в сети 220В.
Подключил arduino к счетчику, к выводам удаленного мониторинга, там похоже стоит опторозвязка.
Вобщем все работает, мощность показывает какое-то время, сутки или 3 часа, по разному.
Счетчик ненужный используется, поэтому там долгое время бывает не бывает нагрузки, при этом светодиод не моргает и в итоге при подключении нагрузки прерывания не срабатывают.
При этом перестает правильно реагировать на millis(), это только-что заметил, т.к. проект включает в себя управление курятником :) регулирует температуру, управляет освещением, и еще температуру дома и на улице показывает. Вобщем входы-выходы все использованы.
В обработчике прерывания никакних сложных действий не производится, один рас вызывается micros() и пара сравнений инкрементов переменных с ключевым словом volatile.
До этого эта-же ардуина с этой-же функцией исправно показывала скорость на машине, там датчик холла был завязан на кардан т.к. датчик на коробке автомате что-то заумирал и скорости не переключались.
Вобщем. мне надо какие-то мысли по поводу как победить это дело.
Если в нагрузку включена лампа 8Вт светодиодная, то он очень радко, раз в несколько минут помаргивает и и вроде как не зависает, а вот зарядник от телефона такого эффекта не дал - зависло за 3 часа.
Счас примеры кода не могу привести, т.к. все на другом компе. Сделан по такому принципу: int pin = 13;
int state = LOW;
unsigned long time;
unsigned long timenext=0;
unsigned long NewData;
unsigned long NewData2;
void setup()
{
Serial.begin(115200);
pinMode(pin, OUTPUT);
pinMode(2, INPUT);
attachInterrupt(0, reader, RISING);
}
void loop()
{
time=millis();
if (time>=timenext)
{
timenext=timenext+1000;
NewData2=NewData; // для отображения
NewData=0;
Serial.println(NewData2);
state=!state;
digitalWrite(pin, state);
}
}
void reader()
{
NewData++;
}
Только в функции reader измеряется интервал по отношению к предыдущему событию.
1. http://arduino.ru/forum/obshchii/vstavka-programmnogo-koda-v-temukommentarii
2. Не вижу слова volatile в приведённом скетче.
Ага, про code понял.
В двух словах если
при объявлении NewData написать volatile в loop вывести NewData на индикатор, то через какое-то время NewData престает изменяться, на вход импульс приходит исправно, если его считывать и выводить на экран в loop то видно.
Я вобще чайник и про voltile узнал позавчера. До этого боролся с "ложными" срабатываниями прерывания при помехе, которая возникала если где-то в сети 220 пощелкать выключателем к которому ничего не подключено, всякие конденсаторно-дроссельные фильтры на входе не помогли. Победил это считывая состояние порта в момент прерывания, ложных срабатываний не стало.
Дело в том что запасной ардуины пока нет и приходится экспериментировать по живому, т.к. куры несуться, а если утром свет не включать вовремя, а я любитель поспать до 11, то не несуться :)
Сегодня причешу код и выложу скетч.
Вешать что-либо на прерывание без хотя-бы простейшего эр-цэ фильтра крайне не рекомендуется......
Устанете дребезг обрабатывать.
Возьмите на вооружение правильную схему: http://arduino.ru/forum/programmirovanie/klass-titanovyi-velosiped-dlya-taktovoi-knopki?page=2#comment-152876
Код, даже не буду оправдываться за стиль, все написано на коленке на ходу между делом. Много всякой экспериментально-отладочной каши.
Проблемное место с 320 строки.
//Sample using LiquidCrystal library #include <LiquidCrystal.h> /* Красный пин Белый минус */ /******************************************************* This program will test the LCD panel and the buttons Mark Bramwell, July 2010 1. try connect to pc if ok - sync date time ********************************************************/ // select the pins used on the LCD panel // 4 5 6 7 8 9 LiquidCrystal lcd(8, 9, 4, 5, 6, 7); int Watts = 0; int temp_1_int = 0; double temp_1_old = 0.0; unsigned long temp_1_millis = 100000; int temp_2_int = 0; double temp_2_old = 0.0; unsigned long temp_2_millis = 100000; //const int pin_kw = 5; //const int pin_sound = 5; const int pin_test = 2; // const int pin_heater = 13; // const int pin_light = 12; // const int pin_backlight = 10; // //const int SoundPin = ; // белый Пин подключения пьезоизлучателя – ШИМ byte BB0[8] = { B11111, B10001, B10001, B10001, B10001, B10001, B10001, B11111 }; byte BB1[8] = { B00000, B00000, B00000, B00100, B01110, B10101, B00100, B00100 }; byte BB2[8] = { B00000, B00000, B00000, B00100, B00100, B10101, B01110, B00100 }; byte BB3[8] = { B11111, B10001, B10001, B10001, B11111, B11111, B11111, B11111 }; byte BB4[8] = { B11111, B10111, B10111, B10111, B10111, B10111, B10001, B11111 }; byte BB5[8] = { B11111, B11001, B10111, B10111, B10111, B10111, B11001, B11111 }; byte BB6[8] = { B11111, B10001, B11011, B11011, B11011, B11011, B11011, B11111 }; byte BB7[8] = { B11111, B11001, B10111, B11011, B11101, B11101, B10011, B11111 }; byte BB8[8] = { B11111, B11001, B10111, B10111, B10111, B10111, B11001, B11111 }; int DelaySound = 1000; // Пауза 1 секунда int cur_pos = 0; // текущий экран int cur_scr = 0; // Главный int max_scr = 3; // Последний экран // define some values used by the panel and buttons int lcd_key = 0; int lcd_key1 = 0; int old_lcd_key = 1; int adc_key_in = 0; int show_points = 0; unsigned long time; unsigned long time_total; unsigned long time_begin; unsigned long time_end; unsigned long time_on; unsigned long cur_time; unsigned long time_on_1; int time_flag = 0; unsigned long time_off; unsigned long cur_sec = 0; unsigned long cur_min = 0; unsigned long cur_hrs = 0; unsigned long set_sec = 0; unsigned long set_min = 0; unsigned long set_hrs = 0; unsigned long kw_total = 0; unsigned long kw_1 = 800; unsigned long kw_2 = 8; int incomingByte = 0; char rxstr[30]; char rxcmd[30]; int rxlen = 0; int i = 0; #define btnRIGHT 0 #define btnUP 1 #define btnDOWN 2 #define btnLEFT 3 #define btnSELECT 4 #define btnNONE 5 // Датчики темпреатуры int TempPin = 2; int temp_src = 0; double temp_1 = 0.0; int TempPin2 = 3; int temp_src2 = 0; double temp_2 = 0.0; double temp_2_on = 7.65; double temp_2_off = 7.9; int temp_2_switch = 0; int TempPin3 = 4; int temp_src3 = 0; double temp_3 = 0.0; int LuxPin = 5; int lux_src = 0; int lux_day = 200; int lux_on = 0; char str0[16]; char str1[16]; // read the buttons int read_LCD_buttons() { adc_key_in = analogRead(0); // read the value from the sensor // my buttons when read are centered at these valies: 0, 144, 329, 504, 741 // we add approx 50 to those values and check to see if we are close if (adc_key_in > 1000) return btnNONE; // We make this the 1st option for speed reasons since it will be the most likely result if (adc_key_in < 50) return btnRIGHT; if (adc_key_in < 195) return btnUP; if (adc_key_in < 380) return btnDOWN; if (adc_key_in < 555) return btnLEFT; if (adc_key_in < 790) return btnSELECT; return btnNONE; // when all others fail, return this... } // создаем метод для перевода показаний сенсора в градусы Цельсия double analog_pin(int pin) { int i; int max = 20; unsigned long term = 0; // Измеряем 10 раз for (i = 0; i < max; i++) { term = term + analogRead(pin); } term = term / max; return term; } 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 testfade() { //С помощью функции analogWrite подаем на порт напряжение от 0 до 5в. //В качестве первого аргумента номер пина, в качестве второго число от 0 до 255 //В качестве примера будем подавать значение от 0 до 255 и наблюдать плавное увеличение яркости for (int i = 0; i <= 255; i++) { analogWrite(pin_light, i); lcd.setCursor(0, 0); lcd.print(i); lcd.print(" "); //Задержка для более плавного эффекта свечения delay(30); } //затухания светодиода for (int i = 255; i >= 0; i--) { analogWrite(pin_light, i); lcd.setCursor(0, 0); lcd.print(i); lcd.print(" "); //Задержка для более плавного эффекта потухания delay(30); } //Выставляем паузу 0.5с delay(500); } /* void alarm() { int i; for (i = 0; i < 200; i++) { tone(pin_sound, 4000); // Воспроизводим сигнал с частотой 1915 Гц delay(10); // Пауза 1 секунда (1000 миллисекунд – значение переменной DelaySound ) – длительность воспроизведения сигнала noTone(pin_sound); // Выключаем звук delay(100); // Пауза 1 секунда (1000 миллисекунд – значение переменной DelaySound ) – длительность воспроизведения сигнала } } */ // Измеряем частоту по прерыванию volatile int hz_count = 0; volatile long int cur_micros = 0; volatile long int cur_micros_1 = 0; volatile long int micros_prev = 0; volatile double Hz_new = 0.0; volatile double Hz = 0.0; void MAP () { if (digitalRead(pin_test) == LOW) { cur_micros_1 = micros(); if (((cur_micros_1 - micros_prev) > 100000) && ((cur_micros_1 - micros_prev) < 1000000000)) { cur_micros = cur_micros_1; Hz = (1000000000.0 / (cur_micros - micros_prev)); Hz = Hz / 1.33333333333; Hz_new = Hz; hz_count++; micros_prev = cur_micros; } } } void setup() { pinMode(pin_test, INPUT_PULLUP); // digitalWrite(pin_test, LOW); attachInterrupt(0, MAP, FALLING); lcd.begin(16, 2); // start the library pinMode(pin_heater, OUTPUT); pinMode(pin_light, OUTPUT); digitalWrite(pin_heater, LOW); // digitalWrite(pin_light, LOW); Serial.begin(9600); lcd.createChar(1, BB0); lcd.createChar(2, BB1); lcd.createChar(3, BB2); lcd.createChar(4, BB3); lcd.createChar(5, BB4); lcd.createChar(6, BB5); lcd.createChar(7, BB6); lcd.createChar(8, BB7); lcd.clear(); cur_scr = 0; } void loop() { cur_micros_1 = micros(); if ((cur_micros_1 - micros_prev) > 10000000) { Hz_new=0; } Watts=Hz_new; lcd_key = read_LCD_buttons(); // read the buttons if (cur_scr > max_scr) cur_scr = 0; /* while (Serial.available() > 0) { incomingByte = Serial.read(); if ((incomingByte == 10) && (rxlen > 2)) { rxstr[rxlen] = incomingByte; Serial.print("RX: "); for (i = 0; i <= rxlen; i++) Serial.print(rxstr[i]); if (rxstr[0] == 35) { if (rxstr[1] == 84) // T { if (rxstr[4] == 58) { set_hrs = rxstr[3] - 48; i = 4; } else { set_hrs = (rxstr[3] - 48) * 10 + (rxstr[4] - 48); i = 5; } set_min = (rxstr[i + 1] - 48) * 10 + (rxstr[i + 2] - 48); set_sec = (rxstr[i + 4] - 48) * 10 + (rxstr[i + 5] - 48); } } rxlen = 0; } else { rxstr[rxlen] = incomingByte; rxlen++; } } */ time_on = 20600; // 6:00 time_off = 79200; // 22:00 cur_time = set_hrs * 60 * 60 + set_min * 60 + set_sec; time = millis() / 1008; // 1009 - корректировка того что часики убегают time = time % 86400; time = cur_time + time; cur_hrs = ((time / 60 / 60) % 24); cur_min = ((time / 60) % 60); temp_src = analog_pin(TempPin); temp_src2 = analog_pin(TempPin2); temp_src3 = analog_pin(TempPin3); temp_1 = Getterm(temp_src); temp_2 = Getterm(temp_src2); temp_3 = Getterm(temp_src3); if (temp_2 < temp_2_on) { temp_2_switch = 1; if (time_flag == 0) { time_on_1 = millis() / 1009; // 1009 - корректировка того что часики убегают time_begin = millis() / 1009; // 1009 - корректировка того что часики убегают time_flag = 1; } } if (temp_2 >= temp_2_off) { if (time_flag == 1) { time_end = millis() / 1009; // 1009 - корректировка того что часики убегают time_total = time_total + (time_end - time_begin); time_flag = 0; } temp_2_switch = 0; } lux_src = analog_pin(LuxPin); // Датчик освещенности if (lux_src > lux_day) { analogWrite(pin_backlight, 255); } else { analogWrite(pin_backlight, 30); } if ((time >= time_on) && (time < time_off) && (lux_src < lux_day)) { // Если в промежутке времени и недостаточно света - включить свет lux_on = 1; digitalWrite(pin_light, HIGH); } else { lux_on = 0; digitalWrite(pin_light, LOW); } if (temp_2_switch == 1) { digitalWrite(pin_heater, HIGH); } else { digitalWrite(pin_heater, LOW); } // Вывод датчиков в COM-порт while (Serial.available() > 0) { incomingByte = Serial.read(); if ((incomingByte == 10) && (rxlen > 2)) { rxstr[rxlen] = incomingByte; Serial.print(cur_hrs, DEC); Serial.print(":"); Serial.print(cur_min, DEC); Serial.write(9); Serial.print(temp_1, DEC); Serial.write(9); Serial.print(temp_2, DEC); Serial.write(9); Serial.print(temp_3, DEC); Serial.write(9); Serial.print(temp_2_switch, DEC); Serial.write(9); Serial.println(""); rxlen = 0; } else { rxstr[rxlen] = incomingByte; rxlen++; } } Serial.print(Hz_new, DEC); Serial.println(""); /* Serial.print(cur_hrs,DEC); Serial.print(":"); Serial.print(cur_min,DEC); Serial.write(9); Serial.print(temp_1,DEC); Serial.write(9); Serial.print(temp_2,DEC); Serial.write(9); Serial.print(temp_3,DEC); Serial.write(9); Serial.print(temp_2_switch,DEC); Serial.write(9); Serial.println(""); */ lcd.clear(); if (cur_scr == 0) { lcd.setCursor(0, 0); if (cur_hrs < 10) lcd.print("0"); lcd.print(cur_hrs); if (show_points == 0) { lcd.print(" "); show_points = 1; } else { lcd.print(":"); show_points = 0; } if (cur_min < 10) lcd.print("0"); lcd.print(cur_min); lcd.print(" "); if ((time >= time_on) && (time < time_off)) { lcd.write(6); } else { lcd.write(1); } if (lux_src >= lux_day) { lcd.write(8); } else { lcd.write(1); } if (lux_on == 1) { lcd.write(5); } else { lcd.write(1); } lcd.write(1); if (temp_2_switch == 1) { lcd.write(7); } else { lcd.write(1); } // Время работы обогревателя в минутах lcd.print(" "); // lcd.print(time_total / 60); // lcd.print(Watts); lcd.setCursor(0, 1); temp_1_int = temp_1 * 10; // if(temp_1_int>0) lcd.print(" "); lcd.print(temp_1_int / 10); if (temp_1 > temp_1_old + 0.1) { temp_1_millis = millis(); temp_1_old = temp_1; lcd.write(2); } else if (temp_1 < temp_1_old - 0.1) { temp_1_millis = millis(); temp_1_old = temp_1; lcd.write(3); } else { lcd.print("."); } if (temp_1_millis + 10000 > millis()) { temp_1_millis = millis(); temp_1_old = temp_1; } lcd.print(temp_1_int % 10); //lcd.print(temp_1, 1); lcd.setCursor(6, 1); if (temp_1 > 0) lcd.print(" "); lcd.print(temp_2, 1); lcd.setCursor(11, 1); if (temp_1 > 0) lcd.print(" "); lcd.print(temp_3, 1); // lcd.setCursor(13, 1); // lcd.print(lux_src,DEC); switch (lcd_key) // depending on which button was pushed, we perform an action { case btnRIGHT: { if (cur_scr == 0) { cur_scr++; if (cur_scr > max_scr) cur_scr = 0; } break; } case btnLEFT: { if (cur_scr == 0) { cur_scr--; if (cur_scr < 0) cur_scr = max_scr; } break; } case btnUP: { break; } case btnDOWN: { break; } case btnSELECT: { //testfade(); cur_scr++; break; } case btnNONE: { break; } } } // Настройка часов else if (cur_scr == 1) { lcd.setCursor(0, 0); if (cur_hrs < 10) lcd.print("0"); lcd.print(cur_hrs); if (show_points == 0) { lcd.print(" "); show_points = 1; } else { lcd.print(":"); show_points = 0; } if (cur_min < 10) lcd.print("0"); lcd.print(cur_min); if (cur_pos == 0) lcd.setCursor(0, 1); if (cur_pos == 1) lcd.setCursor(1, 1); if (cur_pos == 2) lcd.setCursor(3, 1); if (cur_pos == 3) lcd.setCursor(4, 1); lcd.print("-"); switch (lcd_key) // depending on which button was pushed, we perform an action { case btnRIGHT: { cur_pos++; if (cur_pos > 3) cur_pos = 0; break; } case btnLEFT: { cur_pos--; if (cur_pos < 0) cur_pos = 3; break; } case btnUP: { if (cur_pos == 0) { if (set_hrs < 14) set_hrs = set_hrs + 10; } if (cur_pos == 1) { if (set_hrs < 23) set_hrs = set_hrs + 1; } if (cur_pos == 2) { if (set_min < 50) set_min = set_min + 10; } if (cur_pos == 3) { if (set_min < 59) set_min = set_min + 1; } break; } case btnDOWN: { if (cur_pos == 0) { if (set_hrs > 9) set_hrs = set_hrs - 10; } if (cur_pos == 1) { if (set_hrs > 0) set_hrs = set_hrs - 1; } if (cur_pos == 2) { if (set_min > 9) set_min = set_min - 10; } if (cur_pos == 3) { if (set_min > 0) set_min = set_min - 1; } break; } case btnSELECT: { cur_scr++; break; } case btnNONE: { break; } } } // Порог освещенности else if (cur_scr == 2) { lcd.clear(); lcd.setCursor(0, 0); lcd.print(lux_src, DEC); lcd.setCursor(0, 1); lcd.print(lux_day, DEC); lcd.setCursor(10, 0); lcd.print(Watts, DEC); lcd.setCursor(10, 1); lcd.print(hz_count); switch (lcd_key) // depending on which button was pushed, we perform an action { case btnUP: { if (lux_day < 1000) lux_day++; break; } case btnDOWN: { if (lux_day > 0) lux_day--; break; } case btnSELECT: { cur_scr++; break; } } } else if (cur_scr == 3) { lcd.clear(); lcd.setCursor(0, 0); lcd.print(time_total, DEC); switch (lcd_key) // depending on which button was pushed, we perform an action { case btnSELECT: { cur_scr = 0; break; } } } delay(500); }