Форум обсуждения систем  

Вернуться   Форум обсуждения систем "Умный дом", проектов Ардуино, OpenWRT и других DIY устройств > Форум умного дома > Сделай сам

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
Старый 03.07.2015, 07:34   #21
Arhat109
Senior Member
 
Регистрация: 14.06.2015
Адрес: СССР
Сообщений: 122
Вес репутации: 0
Arhat109 is an unknown quantity at this point
По умолчанию Re: Ускоряем и улучшаем скетчи. Ещё одна библиотека.

Это не интересно, не нужно или не работает? Как-то никто так и не проверил библиотеку... так стоит ли продолжать далее?

Вчера весь вечер убил на чтение даташита про прерывания. Задача была сделать замер длительности импульса (Wiring:: pulseIn()) через прерывания.

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

Кроме этого, вторая "засада": в прерывании типа PCINT невозможно (или я так и не понял КАК) узнать от какой конкретно ножки этого уровня оно прилетело. По сути, к примеру PCINT16..23 выведены на ножки Analog8..15 и их удобно использовать как прерывания (16 анлаговых ножек мне точно не надо) ... но одновременно разрешать можно только одну из них, иначе нет способа узнать "какая конкретно сейчас сработала"... а датчиков HC-SR04 у меня 2. Для них и делаю.

И третье: прерываний INT0..7 на Ардуино Мега разведено ... только 5. Из них 2 совмещаются в контроллере с шиной I2C, которая мне нужна "как воздух" (датчик гироскопа, гирокомпаса и дисплей 1602), ещё 2 - это USART1, который планировался как средство связи с приемо-передающими модулями, тот же Bluetooth, и пятое - это PWM ножка, которые все у меня планировались под аппаратный ШИМ на серво моторы (12шт)... и, "как быть"? Отказаться от USART1, заменив его на 2 или 3?

... в общем, требуется совет от бывалых: стоит ли реализовывать замер длительности импульсов в библиотеке через обработку прерываний?
Arhat109 вне форума   Ответить с цитированием
Старый 03.07.2015, 10:39   #22
Admin
Administrator
 
Аватар для Admin
 
Регистрация: 12.04.2010
Адрес: Москва
Сообщений: 9,618
Вес репутации: 9823
Admin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant future
По умолчанию Re: Ускоряем и улучшаем скетчи. Ещё одна библиотека.

Цитата:
Это не интересно, не нужно или не работает? Как-то никто так и не проверил библиотеку... так стоит ли продолжать далее?
Сейчас лето. Дачи, огороды, стройки, отдых и т.д.

Цитата:
Внезапно выяснил, что использовать PCINT не получится, поскольку нет управления режимом прерываний: только по изменению уровня. А требуется переустанавливать с прерывания по фронту на прерывание по спаду, иначе легко можно намерить длительность не того уровня.
В обработчике можно программно все проверять

Цитата:
иначе нет способа узнать "какая конкретно сейчас сработала".
Ответил выше
Admin вне форума   Ответить с цитированием
Старый 03.07.2015, 11:45   #23
Arhat109
Senior Member
 
Регистрация: 14.06.2015
Адрес: СССР
Сообщений: 122
Вес репутации: 0
Arhat109 is an unknown quantity at this point
По умолчанию Re: Ускоряем и улучшаем скетчи. Ещё одна библиотека.

I need help.

Не нашел КАК проверить в обработчике. Он же един на весь вектор PCINT0..2! Флаг прорывания устанавливается общий (там всего три бита), номер ножки, вызвавшей прерывание - не нашел КАК опознать... или есть способ?

Хотя ... если строго для замера длительности импульса ... он жеж "стоять" должен... можно тупо считывать "прерывательные" ножки и смотреть "кто такой вумный"... но. Это ни разу не поможет повесить 2 HC-SR04 на 2 ноги прерывания и замерять параллельно ... хотел поставить 2шт. на сервомотор "спиной друг к другу" и сканировать обе полусферы одновременно... или "почти".

Последний раз редактировалось Arhat109; 03.07.2015 в 11:49.
Arhat109 вне форума   Ответить с цитированием
Старый 03.07.2015, 12:19   #24
Admin
Administrator
 
Аватар для Admin
 
Регистрация: 12.04.2010
Адрес: Москва
Сообщений: 9,618
Вес репутации: 9823
Admin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant future
По умолчанию Re: Ускоряем и улучшаем скетчи. Ещё одна библиотека.

Цитата:
Не нашел КАК проверить в обработчике. Он же един на весь вектор PCINT0..2! Флаг прорывания устанавливается общий (там всего три бита), номер ножки, вызвавшей прерывание - не нашел КАК опознать... или есть способ?
Если упрощенно то так:
Цитата:
if (digitalRaed(требуемый пин)) здесь выполняем обработку ;
Admin вне форума   Ответить с цитированием
Старый 03.07.2015, 14:07   #25
Arhat109
Senior Member
 
Регистрация: 14.06.2015
Адрес: СССР
Сообщений: 122
Вес репутации: 0
Arhat109 is an unknown quantity at this point
По умолчанию Re: Ускоряем и улучшаем скетчи. Ещё одна библиотека.

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

... но мне кажется, что это "как-то ненадежно"...
Arhat109 вне форума   Ответить с цитированием
Старый 03.07.2015, 16:00   #26
Admin
Administrator
 
Аватар для Admin
 
Регистрация: 12.04.2010
Адрес: Москва
Сообщений: 9,618
Вес репутации: 9823
Admin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant futureAdmin has a brilliant future
По умолчанию Re: Ускоряем и улучшаем скетчи. Ещё одна библиотека.

А что смущает? Это же обработчик, в нем можно выполнять любой код, не связанный с другими прерываниями
Admin вне форума   Ответить с цитированием
Старый 04.07.2015, 08:50   #27
Arhat109
Senior Member
 
Регистрация: 14.06.2015
Адрес: СССР
Сообщений: 122
Вес репутации: 0
Arhat109 is an unknown quantity at this point
По умолчанию Re: Ускоряем и улучшаем скетчи. Ещё одна библиотека.

Смущает это (выложу пока то что получается, не компилял ещё):

PHP код:
/**
 * Доступные прерывания в Ардуино Мега 2560:
 * INT0..5 отключает I2C:CSL(21), I2C:SDA(20), USART1:RX(19), USART1:TX(18), pwm2 (T3outB), pwm3(T3outC) соответственно.
 * PC_INT0[0..7] отключает SPI:SS(53), SPI:SCK(52), SPI:MOSI(51), SPI:MISO(50), pwm10(T2outA), pwm11(T1outA), pwm12(T1outB), (pwm13!)
 * PC_INT1[8..10] отключает USART0:RX(0), USART3:RX(15), USART3:TX(14)
 * PC_INT2[16..23] (Analog8..Analog15)
 * .. остальные ножки прерываний контроллера ATmega2560 в Ардуино - отсутствуют.
 * INT0..7 - каждое прерывание использует свой вектор _VECTOR(1..8)
 * PCINT0..2 - на один вектор - 8 ножек, без контроля с какой ноги прилетело и без управления типом прерываний.
 */
#define _ARHAT_ 1
#include "arhat.h"

#define PULSE_STATES    3
#define PULSE_BUSY      1
#define PULSE_SECOND    2
#define PULSE_OK        3
#define PULSE_TIMER     4
#define PULSE_ERROR     128    

typedef struct {
  
uint32_t      res;            // state==PULSE_OK? pulse time in micros : not valid data.
  
uint8_t       state;          // @see PULSE_STATES constants status for this measuring.
  
uint8_t       timer;          // timeout number in timer events queue
  
uint8_t       pin;            // interrupt pin for this measuring
Pulse;

typedef struct {
  
Event;

uint8_t         pcint2old        0;
signed char     pcint2numbres[8] = {0,0,0,0,0,0,0,0};
extern Pulse    Pulses[];
extern Event    timeEvents[];

/**
 * Обработчик прерывания для замера времени между фронтом и спадом сигнала
 * на ножке прерывания PCINT2 (Analog8..15) "на выбор":
 * 
 * При первом срабатывании - фиксирует "фронт" (сохраняет значение таймера)
 * и изменяет режим своей работы на поиск спада.
 * При втором срабатывании - фиксирует спад сигнала и сохраняет разность времени в микросекундах.
 * Отключается от прерываний.
 */
void pulse_pcint2()
{
  
uint8_t       regK PINK;              // Первым делом читаем ноги регистра К (Analog8..15)
  
uint8_t       temp pcint2old;         // и предыдущее их состояние
  
  
pcint2old regK;                       // сразу сохраняем новое состояние
  
regK = (temp regK) & PCMSK2;          // ищем сработавшую ножку
  
temp 0;
  while(
regK /= 2) { temp++; };           // temp=[0..7] номер бита прерывания!
  
regK pcint2numbers[temp];             // получаем номер структуры где храним данные
  
  
switch( Pulses[regK].state PULSE_STATES )
  {
    case 
PULSE_BUSY:                      // first measuring! store current micros()
      
Pulses[regK].res micros();
      
Pulses[regK].state PULSE_SECOND;
      return;

    case 
PULSE_SECOND:                    // second measuring! calc pulse time:
      
Pulses[regK].res micros() - Pulses[regK].res;
      
Pulses[regK].state PULSE_OK;      // измерение завершено, данные действительны.
      
break;

    case 
0:                               // ошибка в данных!
    
case PULSE_OK:
      
Pulses[regK].state PULSE_ERROR;
      break;
  }
  
PCMSK2 &= ~(1<<temp);                   // запрещаем обработанное прерывание
  
temp Pulses[regK].timer;              // ищем запущенный таймаут
  
if( temp ) {
    
timeEvents[temp] = 0;                 // снимаем запущенный тайм аут.
    
Pulses[regK] = 0;                     // и помним что его больше нет
  
}
}

/**
 * Запуск измерения длительности сигнала на ножке через прерывания PCINT2
 * Пока для HC-SR04: макс. дальность = 5м или 29800мксек.
 * 
 * @param uint8_t pulseIndex -- номер структуры замеров длительности в статическом массиве
 * @param uint32_t timeout   -- [30000 мксек] время ожидания замера основным таймером
 */
void pulse_start(uint8_t pulseIndexuint32_t timeout=30000)
{
  
uint8_t       intNumber,temp;

  
intNumber = ((Pulses[p].pin) & 7);      // ищем ногу по общему номеру пина[Analog8..15]
  
pcint2numbers[intNumber] = pulseIndex;  // сохраняем номер активной структуры
  
Pulses[p].state PULSE_BUSY;           // закрываем доступ "идет замер"
  
intNumber 1<<intNumber;               // получаем маску для битовых операций
  
temp = ~intNumber;                      // и её инверсию для сброса бита
  
pcint2old &= temp;                      // бит в "было раньше" = 0
  
DDRK |= intNumber;                      // нога "на выход"
  
PORTK &= temp;                          // ?надо? сброс ножки прерывания в 0 ("echo")
  
DDRK &= temp;                           // нога "на вход"
// @TODO Установить таймаут в таймере!!!
  
PCMSK2 |= intNumber;                    // и только теперь разрешаем прерывание с этой ноги

Функция pulse_pcint2() - это будущий обработчик прерывания PCINT2. В ней, побитный xor с предыдущим состоянием ноги позволяет выделить из регистра "сработавшую ногу прерывания", а логическое домножение на регистр маски - выключить те биты, которые не участвуют в обработчике.

Следующим циклом я подсчитываю "номер" сработавшего бита.

Это не есть "хорошее решение". Ибо "если вдруг", одновременно (в рамках одного вызова обработчика) происходит 2 и более "срабатываний" (например, прерывания были запрещены длительное время в скетче - понятно что "Г-кодинг"), то по-хорошему надо обработать ВСЕ сработавшие ножки... как?

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

Последнее решение "в целом" мне кажется перспективней. И сильно. "Робот" - это всяко обыкновенный конечный автомат, работающий по возникающим событиям.

... в обшем, я "таймаут в разработке" и взял по причине того что "доперло": нафиг не надо улучшать Wiring. Требуется совершенно иной подход.
Arhat109 вне форума   Ответить с цитированием
Старый 04.07.2015, 14:57   #28
Arhat109
Senior Member
 
Регистрация: 14.06.2015
Адрес: СССР
Сообщений: 122
Вес репутации: 0
Arhat109 is an unknown quantity at this point
По умолчанию Re: Ускоряем и улучшаем скетчи. Ещё одна библиотека.

Так. Похоже это был какой-то глюк в моей среде 1.6.4 ... переставил себе заново эту версию и ... опаньки! Забыл переименовать wiring.c ... а оно возьми да и скомпиляйся без ошибок.

Похоже что библиотекарь таки работает "как и положено": подшивает то, что есть в файлах, если оно есть ИЛИ берет из библиотеки core.a если его нет..

Существенно меняет ситуацию: можно НЕ переименовывать ничего... и даже с main.cpp "поиздеваться вдоволь".

поправил первый пост.
Arhat109 вне форума   Ответить с цитированием
Старый 06.07.2015, 10:36   #29
Arhat109
Senior Member
 
Регистрация: 14.06.2015
Адрес: СССР
Сообщений: 122
Вес репутации: 0
Arhat109 is an unknown quantity at this point
По умолчанию Re: Ускоряем и улучшаем скетчи. Ещё одна библиотека.

Допилил замер длительности импульса через прерывания PCINT2 ... возник вопрос с таймаутами, ибо датчик в реальности вполне себе может срабатывать "через раз":

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

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

Это - плохо? Переходить на стандартные "очереди" на указателях и malloc()? Насколько "опасно" вызывать процедуры таймаутов из обработчика прерывания по таймеру (активизируется примерно каждую миллисекунду, пашет с закрытыми прерываниями "по определению") ... не получится так, что пачка возникших таймаутов заломает всю обработку прерывания? Есть решения лучше?
Arhat109 вне форума   Ответить с цитированием
Старый 21.07.2015, 07:18   #30
Arhat109
Senior Member
 
Регистрация: 14.06.2015
Адрес: СССР
Сообщений: 122
Вес репутации: 0
Arhat109 is an unknown quantity at this point
По умолчанию Re: Ускоряем и улучшаем скетчи. Ещё одна библиотека.

Часть библиотеки для "автоматного программирования":

Код:
// ==================== то, что должно было быть определено в Wiring ====================== //
/**
 * Time State Control Simple Library. Prefix for this: TSC_ (tsc_)
 *
 * Библиотека создания простых конечных автоматов с задержками исполнения по времении
 * в миллисекундах через функцию millis().
 *
 * @author Arhat109 at 2015-07-18
 * @see Arhat.lib::examples/TSC_Blink/TSC_Blink.ino
 */
typedef unsigned long TSC_Time;      // переопределение "на будущее": не всегда нужен long
typedef void (*TSC_Command)(void);   // вводим определение типа "команда КА" тут просто процедура без параметров
 
// вводим определение типа ячейки хранения состояний автомата:
typedef struct {
  uint8_t       state;          // номер следующего состояния в таблице переходов
  TSC_Command   command;        // команда (метод) для исполнения действий состояния
  TSC_Time      timeout;        // временной интервал следующего состояния (мсек)
} TSC_Step;
 
// вводим определение типа для хранения текущего состояния конечного автомата (КА)
typedef struct {
  uint8_t       state;          // текущий номер исполняемого состояния КА
  TSC_Time      timeout;        // текущий интервал, которого надо дождаться
  TSC_Step *    table;          // таблица переходов этого КА
} TSC_Control;
 
void tsc_init( TSC_Control *_tsc, TSC_Step * _table, uint8_t _state, TSC_Time _wait );
void tsc_next( TSC_Control *_tsc, uint8_t _state, TSC_Time _wait );
void tsc_step( TSC_Control *_tsc );
Это файл реализации функций библиотеки time_state_control.c
Код:
// ======== TimeStateControl.c -- реализация библиотеки: ======== //
include "TimeStateControl.h"
// метод сохранения текущих данных для конечного автомата:
void tsc_init( TSC_Control *_tsc, TSC_Step * _table, uint8_t _state, TSC_Time _wait )
{
    _tsc->table = _table;                 // сохраняем теблицу переходов для этого КА
    tsc_next(_tsc, _state, _wait);        // устанавливаем его текущее состояние в начальное
}
 
// метод перехода к следующему шагу конечного автомата:
void tsc_next( TSC_Control *_tsc, uint8_t _state, TSC_Time _wait )
{
    _tsc->state = _state;                      // устанавливаем следующее состояние
    _tsc->timeout = millis() + _wait;          // и его время ожидания
}
 
// метод "шаг цикла КА":
// параметр - указатель на состояние заданного КА.
void tsc_step( TSC_Control *_tsc )
{
  if( millis() >= _tsc->timeout )         // если событие, переключающее КА - наступило:
  {
    TSC_Step * current;                   // определяем место хранения структуры состояния КА
 
    current = _tsc->table + _tsc->state;  // и находим "текущее состояние КА"
 
    current->command();                            // исполняем команду
    tsc_next(_tsc, current->state, current->timeout); // и устанавливаем следующий шаг КА
  }
}
Arhat109 вне форума   Ответить с цитированием
Ответ

Метки
arduino mega 2560, скетч, ардуино


Здесь присутствуют: 7 (пользователей: 0 , гостей: 7)
 

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

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход


Текущее время: 02:01. Часовой пояс GMT +3.


Powered by vBulletin® Version 3.8.5
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd. Перевод: zCarot
Яндекс.Метрика