-
Re: Прерывания в Arduino.
хочу попробовать сделать коммутатор на скутер, суть такова:
1. считать импульс с датчика Холла
2. запустить таймер с учетом количества оборотов, прока что будет без ФУОЗ
3. при срабатывании таймер выдать искру, ну и все по новой.
Главное чтобы это все не тормозило основную программу, вот и подумал сделать через прерывания. Уже что-то началось получаться ;)
-
Re: Прерывания в Arduino.
А длительность импульса зачем измерять?
Вот на основе этого скетча можно сделать то что тебе нужно
PHP код:
#include <util/delay.h>
volatile unsigned int tachBuf;
unsigned long tachValue;
ISR(TIMER1_CAPT_vect)
{
TCNT1 = 0;
tachBuf = ICR1+2;
}
//********************************************************************
void setup()
{
pinMode(8, INPUT); //Вход для импульсов спидометра
pinMode(6, OUTPUT);//выход ШИМ
TCCR0B = TCCR0B & 0b11111000 | 5;//частота ШИМ
analogWrite(6, 128); //Запустить ШИМ
digitalWrite(8, HIGH); // включить подтяжку входа
Serial.begin(115200);
TIM_Init();//инициализация таймера
_delay_ms(300);
}
//********************************************************************
void loop()
{
cli();
tachValue =250000/tachBuf;
Serial.print("freq=");
Serial.println(tachValue,DEC);
tachBuf=1;
sei();
_delay_ms(300);
}
//********************************************************************
void TIM_Init(void)
{
TIMSK1=(1<<ICIE1);
TCCR1A=(0<<COM1A1)|(0<<COM1A0)|(0<<WGM11)|(0<<WGM10);
TCCR1B=(1<<ICNC1)|(1<<ICES1)|(0<<WGM13)|(0<<WGM12)|(0<<CS12)|(1<<CS11)|(1<<CS10);
TCNT1 = 0;
}
-
Re: Прерывания в Arduino.
1. этот код работает от 250Гц, это меня не устраивает
2. мне длительность импульса не надо мерить, мб я не совсем точно объяснил. вот что мне надо в идеале:
а. ловим импульс от датчика (пока что буду ловить по спаду)
б. в зависимости от количества оборотов на данный момент запустить таймер
в. когда таймер сработает он должен выдать коротко временный импульс и выключиться
-
Re: Прерывания в Arduino.
-
Re: Прерывания в Arduino.
Цитата:
Сообщение от
sirik
...
2. мне длительность импульса не надо мерить,... в зависимости от количества оборотов ...
Длина импульса и есть "количество оборотов": либо длину импульса либо период - что-то одно из двух придётся мерить.
-
Re: Прерывания в Arduino.
т.е. получается для статистики (т.е. для тахометра) достаточно измерить длину импульса.. спасибо за подсказку, не догадался
-
Re: Прерывания в Arduino.
Гораздо точнее будут показания если измерять частоту, в моем примере как раз частота и измеряется
-
Re: Прерывания в Arduino.
Доброго времени Уважаемый Chip, я новичёк в прогрммировании *duino, и уперся в прерывния, есть такая задача зажигать СД на 6-50 мс (регулируется переменником) с паузой 5-60 сек (регулируется другим переменником), значения выводятся на LCD я сделал это с помощью delay, но проц виснит если пауза дольше 30ти сек и вывод на LCD опаздывает (как и регулировка) на длину этих delay, начал копать и до капал до прерыванию по таймеру, но не могу найти хоть что либо похожее под мою ситуацию для примера... Вы не могли бы на брасать хотябы принцип, буду очень благодарен...
-
Re: Прерывания в Arduino.
Возьми пример с MsTimer2
PHP код:
//Выполнение процедуры по прерыванию таймера.
#include <MsTimer2.h>
void flash_led() //обработчик прерывания
{
digitalWrite(13, HIGH);
delay(30); //длительность импульса
digitalWrite(13, LOW) ;
}
void setup()
{
pinMode(13,OUTPUT);
MsTimer2::set(30000, flash_led); // будет срабатывать каждые 30сек.
MsTimer2::start(); //включить таймер
}
void loop()
{
//здесь может быть Ваш код
}
-
Re: Прерывания в Arduino.
Цитата:
Сообщение от
Chip
Возьми пример с MsTimer2
Спасибо огромное, по моему то что нужно....
-
Re: Прерывания в Arduino.
Вот только добрался до експерементов и оказалось что ms timer2 таки считается в мс а вот таймер импульса почему то в микро сек. т.е. чтоб поставить допустим импульс длит 1сек на нем нужно поставить 100000, я что то не так делаю???
Цитата:
void flash_led() //обработчик прерывания
{
digitalWrite(ledPin, HIGH);
delay(100000); //длительность импульса 1 сек
digitalWrite(ledPin, LOW) ;
}
void setup() {
// declare the ledPin as an OUTPUT:
pinMode(ledPin, OUTPUT);
MsTimer2::set(1000, flash_led); // будет срабатывать каждые 1 сек.
MsTimer2::start(); //включить таймер
-
Re: Прерывания в Arduino.
Таймер импульса, это что?
-
Re: Прерывания в Arduino.
Зачем в flash_led находится делэй?
Код неверный.
PHP код:
boolean LedStatus=false; //триггер состояния Led
void flash_led() //обработчик прерывания
{
LedStatus = !LedStatus; //переключаем триггер
if (LedStatus) //проверяем состояние триггера
{
digitalWrite(ledPin, HIGH); //включаем, если триггер в true
}
else
{
digitalWrite(ledPin, LOW) ; // выключаем, если триггер в false
}
}
void setup() {
// declare the ledPin as an OUTPUT:
pinMode(ledPin, OUTPUT);
MsTimer2::set(1000, flash_led); // будет срабатывать каждые 1 сек.
MsTimer2::start(); //включить таймер
Код сознательно упрощен для понимания.
-
Re: Прерывания в Arduino.
-
Re: Прерывания в Arduino.
Сча изобрАзим :D
PHP код:
volatile int led_time = 5; //5 сек из 60 будет гореть
volatile int led_counter = 0; //счетчик
void flash_led() //обработчик прерывания
{
if (led_time>led_counter) //
{
digitalWrite(ledPin, HIGH); //горит, пока счетчик считает до 5
}
else
{
digitalWrite(ledPin, LOW) ; // не горит оставшееся время (55 сек в твоем случае)
}
led_counter++;
if (led_counter==60) led_counter=0; //обнуляем счетчик
}
-
Re: Прерывания в Arduino.
Цитата:
Сообщение от
BlkDem
Сча изобрАзим :D
PHP код:
volatile int led_time = 5; //5 сек из 60 будет гореть
volatile int led_counter = 0; //счетчик
void flash_led() //обработчик прерывания
{
if (led_time>led_counter) //
{
digitalWrite(ledPin, HIGH); //горит, пока счетчик считает до 5
}
else
{
digitalWrite(ledPin, LOW) ; // не горит оставшееся время (55 сек в твоем случае)
}
led_counter++;
if (led_counter==60) led_counter=0; //обнуляем счетчик
}
Прошу прощения что не появлялся....
Дело в том что длина "high"(импульс) и длина "low"(пауза), величины регулируемые 5-50МС и 5-50с соответственно...
Так же столкнулся с такой проблемой при подаче питания на МК и до окончания инициализации на ledPin присутствует "1" тем самым открыт клапан почти 4 сек (льёт житкость рекой), можно ли изначально задать "0" на нужной ноге?
-
Re: Прерывания в Arduino.
Схему и скетч выложи, посмотрю что можно сделать
-
Re: Прерывания в Arduino.
У меня в механическом спидометре, на TLC-80, обнаружился геркон, который замыкается 4 раза за 1 оборот вала (одной ногой сидит на земле).
Я подозревал, что геркон может дребезжать, поэтому решил сначала потренироваться на кошках велосипеде. Там так же имеется геркон.
Т.к. срабатывание геркона приводит к появлению логического нуля я решил использовать attachInterrupt(0, int_on, LOW);
Беру второй пример, немного модифицирую для вывода значений:
PHP код:
#define PinA 2
static boolean output = HIGH;
int pulse = 0;
void setup()
{
pinMode(PinA, INPUT);
digitalWrite(PinA, HIGH); // подключить подтягивающий резистор
attachInterrupt(0, int_on, LOW); // настроить прерывание interrupt 0 на pin 2
Serial.begin(9600);
}
void loop()
{
delay(100);
Serial.println(pulse);
}
// обработка прерывания
void int_on()
{
digitalWrite(13, (output==HIGH) ? output=LOW : output=HIGH);
pulse++;
}
Кручу колесо рукой и выясняется, что при прохождении магнита около геркона фиксируется от 2 000 - 15 000 вызовов прерывания, в зависимости от скорости вращения.
Меняем работу с прерыванием на attachInterrupt(0, int_on, CHANGE), получаем от 1 до 5 вызовов за одно прохождение.
RISING дает 2 вызова: первый когда геркон замыкатеся, второй когда размыкается и, наконец FALLING стабильно дает 2 вызова при замыкании геркона.
Интересно получается. Судя по описанию:
LOW - вызов прерывания когда пин устанавливается в 0.
CHANGE - пин меняет состояние (0->1 или 1->0)
RISING - 0 -> 1
FALLING - 1 -> 0
Т.е. по всех случаях кроме CHANGE должен происходить один вызов прерывания за один проход магнита мимо датчика.
В итоге дорабатываю код таким образом, что бы получать один вызов в момент замыкания геркона.
PHP код:
#define PinA 2
static boolean output = HIGH;
int pulse = 0;
bool prev = false;
void setup()
{
pinMode(PinA, INPUT);
digitalWrite(PinA, HIGH); // подключить подтягивающий резистор
attachInterrupt(0, int_on, FALLING); // настроить прерывание interrupt 0 на pin 2
Serial.begin(9600);
}
void loop()
{
delay(100);
Serial.println(pulse);
}
// обработка прерывания
void int_on()
{
digitalWrite(13, (output==HIGH) ? output=LOW : output=HIGH);
if(!prev)
{
pulse++;
}
prev = !prev;
}
Завтра по дороге на работу опробую это в машине.
-
Re: Прерывания в Arduino.
Я бы в обработчике прерывания выключал прерывание на момент обработки:
PHP код:
void int_on()
{
detachInterrupt(int_on);
digitalWrite(13, (output==HIGH) ? output=LOW : output=HIGH);
pulse++;
attachInterrupt(0, int_on, FALLING);
}
-
Re: Прерывания в Arduino.
Лучше поставить конденсатор 0,1мкф параллельно геркону
-
Re: Прерывания в Arduino.
Сегодня провел испытание на автомобиле: примерно 8 импульсов за 1 оборот колеса. Что получается ~ 31см/ на импульс. Можно начинать писать спидометр. Как раз пригодится MsTimer2 :)
-
Re: Прерывания в Arduino.
Пытался при помощи приведенного мною выше кода отслеживать появление +5в. на Pin 2. Не получается не при каких значениях 3-го параметра функции attachInterrupt.
Испытывал при помощи проводка подключая попеременно его то к земле, то к 5в. Значение переменной pulse растет только когда к земле провод подключаю.
-
Re: Прерывания в Arduino.
Тебе импульсы считать нужно?
-
Re: Прерывания в Arduino.
Специально зарегистрировался на этом форуме, т.к. сколько я лазил лазил по рус. инету, спецом по Ардуине Chip наверно в 5терку лучших вошел бы.
Хотел у вас спросить. Сам я фермер, жизнь заставила писать для МК разнообразные программы для хозяйства, т.к. нужна гибкость и получение того, что мне конкретно от МК нужно. Раньше я писал проги на асемблере под пики, но когда код получался под 16000 команд написанных руками, мозг начал просить пощады (т.к .в памяти нужно было хранить для чего то для чего это).
В начале я скачал прогу Флоукоде и за 1н день написал простую прогу (терморегулятор + димер) для неизвестного мне контроллера и оно все заработало.
Потом купил Ардуино на атмеге 2560, довольно быстро получилось прикрутить символьный ЖКИ, датчики DHT, а потом если честно - разочарование, потому как не могу разобраться с критичными для моих применений вещами:
1. Как пользоваться кучей таймеров атмеги 2560 и пользоваться их прерываниями?
2. Почему DHT датчики так сильно тормозят на ардуино?
мне вот что в хозяйстве, в основном нужно - работа с АЦП, димеры - плавные регулировки напряжения для вентиляции, освещения, насосов отопления, т.е. обычное фазовое управление на симисторы. На пике это в пол тыка делалось прерываниями, по убыванию фронта на INT и (желательно быстрый) отсчет таймера, на каждый симистор должен работать отдельный таймер (обычно были задействованы все 4ре таймера) , все это крутилось себе в прерываниях и особо не тормозило работу основной программы, можно было спокойно себе лазить в меню, изменять параметры.
А сколько я видел примеров скетчей на ардуино - все идет через делей (!?) что за изврат??? или 1н единственный таймер №2 :(
В английском я не очень, по пикам хоть есть хорошие описания на русском, полностью переведенные пдфки, а по ардуине того, что мне надо вообще не нашел :(.
Поэтому только на вас у меня вся надежда.
-
Re: Прерывания в Arduino.
Я извиняюсь, но мое сообщение по каким то причинам не попало сюда
Не буду заново писать, лучше спрошу
Может Вам примеры кода показать?
-
Re: Прерывания в Arduino.
Chip буду очень признателен.
Интересуют прерывания по таймерам Атмеги 2560, установка значений в таймер (для фазовых задержек), по INT прерываниям я уже вроде разобрался. желательно чтоб без библиотек.
-
Re: Прерывания в Arduino.
Конкретно для меги я ни разу не писал, Примеры для Arduino Nano приведу
Многоканальный Dimmer на Arduino Nano на Mega будет работать если заменить фаил Nanopins.h на cyberpins.h
Пример использования Timer1
Вся информация по регистрам таймеров в Datasheet есть, к сожалению переводить Ds нет времени
но вот например нашел кое что у себя, коментарии к некоторым регистрам и флагам
Думаю этого должно быть достаточно для самостоятельного изучения
Код:
void Setup_TIMER2()
{
// TIMSK2 &= ~(1<<TOIE2); //разрешения прерывания по переполнению таймера/счетчика Т2
TCCR2A &= ~((1<<WGM21) | (1<<WGM20));// Режим работы таймера/счетчика
TCCR2B=((0 << CS22) | (0 << CS21) | (1 << CS20)) //Делитель 0
//ASSR &= ~(1<<AS2); //Выбор источника синхронизации таймера если AS2=0 от системного генератора
//ASSR|=(1<<AS2); // Тактировать T2 от асинхронного генератора таймера
TCNT2 = TCNT2_Const; // 16000000/256/100/64=8 tcnt2=256-8=248.
TIMSK2 |= (1<<TOIE2);//Разрешение прерывания по переполнению Т2.
// TIMSK2|=(1<<OCIE2); // Разрешить прерывание по совпадению Т2.
}
void loop()
{
}
ISR(TIMER2_OVF_vect)//вектор прерывания по переполнению таймера
{
TCNT2=0;
}
ISR(TIMER2_COMPA_vect) //Обработчик прерывания по совпадению с OCR2
{
TCNT2=0;
}
-
Re: Прерывания в Arduino.
спасибо большое :) скажу откровенно по вашим материалам, материалам этого форума, можно сделать одну из сильнейших по всему русскоязычному инету ветку по ардуино.
Огромный вам респект.
-
Re: Прерывания в Arduino.
Если что то будет не понятно, спрашивайте
-
Re: Прерывания в Arduino.
Извиняюсь что не писал долго, проект был отложен и теперь снова к нему вернулся и наступил на грабли,
Цитата:
#include <LiquidCrystal.h>
#include <MsTimer2.h>
const int sensorPin = A1; // select the input pin for the potentiometer
const int sensor1Pin = A2;
int ledPin = 13; // select the pin for the LED
int sensorValue = 0; // variable to store the value coming from the sensor
int sensor1Value = 0;
int ledValue = 0;
int led1Value = 0;
// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
void flash_led() //обработчик прерывания
{
digitalWrite(ledPin, HIGH);
delay(led1Value); //длительность импульса
digitalWrite(ledPin, LOW) ;
}
void setup() {
// declare the ledPin as an OUTPUT:
pinMode(ledPin, OUTPUT);
MsTimer2::set(ledValue, flash_led); // будет срабатывать каждые 30сек.
MsTimer2::start(); //включить таймер
// set up the LCD's number of columns and rows:
lcd.begin(16, 2);
}
void loop() {
// read the value from the sensor:
sensorValue = analogRead(sensorPin);
sensor1Value = analogRead(sensor1Pin);
lcd.setCursor(0, 1);
// map it to the range of the analog out:
ledValue = map(sensorValue, 0, 1023, 5000, 60000);
led1Value = map(sensor1Value, 0, 1023, 6, 60);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Pause ");
lcd.print(1000 / ledValue);
lcd.print(" ");
lcd.setCursor(0, 1);
lcd.print("impuls ");
lcd.print(led1Value);
lcd.print("ms ");
}
показания на дисплее появляются по буквенно с паузой в 1сек, pin13 светится всё время, уже запутался полностью с этим прерыванием...
-
Re: Прерывания в Arduino.
1. unsigned int ledValue = 0; возможно глюк эмуляции, но знаковая переменная не может принять значение 60000.
2. это можно сделать без отдельного таймера, воспользовавшись millis. вот пример. там как бы все расписано. delay(led1Value) по-моему вполне допустим - 60мс не так много.
вот код. ставится в цикл.
PHP код:
unsigned long currentMillis = millis();
if(currentMillis - previousMillis > ledValue)
{
previousMillis = currentMillis;
digitalWrite(ledPin, HIGH);
delay(led1Value);
digitalWrite(ledPin, LOW);
}
3. если хочется сделать через отдельный таймер, можно так. громоздко. да и таймер с периодом 1мс и так есть.
PHP код:
MsTimer2::set(1, flash);
void flash()
{
if(digitalRead(ledPin)==HIGH)
{
time1++;
if(time1>=led1Value)
{
digitalWrite(ledPin,LOW);
time2=0;
}
}
if(digitalRead(ledPin)==LOW)
{
time2++;
if(time2>=ledValue)
{
digitalWrite(ledPin,HIGH);
time1=0;
}
}
}
оба варианта рабочие
-
Re: Прерывания в Arduino.
Цитата:
Сообщение от
manu_245
оба варианта рабочие
спасибо огромное ща попробую....
upd...
применил первый вариант всё отлично заработало, ещё раз огромное спасибо за подсказку...
-
Re: Прерывания в Arduino.
Всем привет. Я новичёк на этом форуме, поэтому тему создать не могу... мало сообщений. Поэтому вопрос: собственно у меня есть желание сделать автоматическую горелку на отработанном масле, для отопления бокса. Сам занимаюсь ремонтом авто... диагностика и тд. Есть атмега 2050, ЛСД- дисплей 20Х4 с I2C протоколом, датчики температуры и релейный блок с опторазвязкой. Вроде всё, что нужно есть. Теперь самое интересное... Как организовать опрос клавиатуры? На данный момент реализовал на Timer01 с самой маленькой частотой опроса ~ 50 Гц. Как часто опрашивать датчики температуры, это которые однопроводные, у меня по плану их будет 4-8 шт. и стоит ли их опрашивать в цикле прерывания? Как организовать структурное меню, типа текущие параметры, установки, аварийная сигнализация и тд... в смысле линейного или векторного программирования? Стоит ли выводить ШИМ на масляный насос и нагреватель масла или можно просто реле поставить? Корохе много вопросов...