1YHAIhwx

Arduino некорректное значение micros()

9 сообщений в этой теме

1YHAIhwx    3

Я пытаюсь захватить сигнал с ИК-пульта ДУ. Делаю это при помощи Arduino Micro 16 МГц с подключенным к нему фотоприёмником TSOP1736. Код следующий:

const int ARDUINO_MICRO_INTTERRUPT_ON_PIN3 = 0;
const int BUFFER_LEN = 40;

volatile unsigned long periods[BUFFER_LEN];
volatile int i = 0;
volatile unsigned long lastMicros = 0;
volatile unsigned long mcs;
volatile boolean isRunning = false;

void sensorInterruptHandler() {
  isRunning = true;
}

void setup() {
 attachInterrupt(ARDUINO_MICRO_INTTERRUPT_ON_PIN3, sensorInterruptHandler, CHANGE);  
 Serial.begin(9600);
}

void loop() {
  if(!isRunning) {
     return; 
  }
  if(i == BUFFER_LEN) {
    detachInterrupt(ARDUINO_MICRO_INTTERRUPT_ON_PIN3);
    for(int x = 1; x < BUFFER_LEN; ++x) {
       Serial.print(periods[x]);
       Serial.print(" ");
    }
    Serial.println();
    Serial.flush();
    lastMicros = 0;
    delay(1500);
    i = 0;
    attachInterrupt(ARDUINO_MICRO_INTTERRUPT_ON_PIN3, sensorInterruptHandler, CHANGE);
  } else {
    mcs = micros();
    if(lastMicros > mcs) {
       Serial.print("Overflow!"); 
    }
    periods[i] = mcs - lastMicros;
    lastMicros = mcs;
    ++i;
  }
  isRunning = false;
}

Работает следующим образом: всякое изменение уровня на ножке 3 вызывает установку флага isRunning. Главный цикл проверяет установку флага, если он установлен, записывает в буфер periods промежуток времени в микросекундах, в течении которого на ножке не менялся логический уровень. Если буфер заполнен, его содержимое выводится в UART и процесс повторяется. Считываю я всегда один и тот же сигнал, представленный на изображении. И проблема в том, что периодически я получаю совершенно некорректную величину временного промежутка, которую не могу объяснить даже переполнением (для проверки гипотезы о переполнении была вставлена проверка - сообщение о переполнении не печатается). Ниже массив данных, которые я получаю, звездочками отмечены проблемные считывания.

2680 900 496 808 520 376 512 368 468 856 908 428 460 424 468 424 464 416 464 424 464 420 468 420 468 420 460 424 464 424 464 420 468 420 908 416 460 904 876 
2684 896 484 820 520 368 520 368 *1344* *1312* 520 368 528 360 456 428 464 420 468 420 468 420 468 416 464 424 468 420 464 420 468 420 908 416 464 872 904 *83656* 2684 
2680 900 492 816 524 360 520 368 464 860 908 428 460 428 460 424 464 424 468 416 472 416 460 424 464 424 464 424 468 416 460 428 460 424 904 424 468 864 912 
2680 904 492 812 516 372 516 368 *1356* *1304* 516 372 516 368 468 428 460 420 460 424 464 420 468 420 468 420 460 432 456 424 464 424 912 412 468 864 904 *83656* 2684 
2676 904 488 816 524 364 524 364 *1348* *1308* 524 364 524 364 460 424 464 424 468 420 468 416 460 424 464 424 468 420 468 416 460 428 912 412 468 896 880 *83652* 2680 
2676 904 496 812 520 364 524 364 460 864 912 424 468 416 472 416 460 424 464 424 468 420 468 416 460 428 460 428 464 420 468 416 472 424 904 416 464 896 880

Почему я получаю эти странные значения? Эффект повторяется с возмутительным постоянством, и если значения 1344, 1312 ещё как-то можно объяснить, то появления промежутка в 83656 мкс мне совсем не понятно. Что же я делаю не так и откуда берутся столь странные значения? Притом они не случайны и придерживаются какого-то диапазона. Позиция проблемных периодов тоже остаётся неизменной. При подключении датчика вместо микрофона и захвата сигнала при помощи Audacity изменения периода импульсов не наблюдаю.

 

signal.png

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Быстрый заказ печатных плат

Полный цикл производства PCB по низким ценам!

  • x
    мм
Заказать Получить купон на $5.00
Yurkin2015    290

А почему такая странная проверка флага?

47 минут назад, 1YHAIhwx сказал:

if(!isRunning) { return; }

сразу после return программа выходит из loop(), что-то там ещё делает, потом возвращается обратно в loop(). Вот иногда вне этого loop() программа занята чем-то, и набегает лишнее время.

Лучше так проверять

while(!isRunning) { }

Да, ещё нужно внешний while(1){ текст процедуры} поставить, тогда программа точно не будет вылетать из этого loop() 

Изменено пользователем Yurkin2015

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
1YHAIhwx    3
Quote

сразу после return программа выходит из loop(), что-то там ещё делает

Выходит куда и делает что? Напоминаю, функция loop() {} в ардуинодиалекте аналогична коду while(true){}. Таким образом, код

void loop() {
    if(!isRunning) {
        return;
    }
    // do something useful here
}

функционально идентичен
 

while(true) {
    if(!isRunning) {
        continue;
    }
}

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Yurkin2015    290

При выходе из loop() программа занимается отправкой байтов по Serial интерфейсу

#include <Arduino.h>

int main(void)
{
 init();

#if defined(USBCON)
 USBDevice.attach();
#endif
 
 setup();
    
 for (;;) {
 loop();
 if (serialEventRun) serialEventRun();
 }
        
 return 0;
}

 

Поэтому предлагаю, пока не выполнилось условие

if(i == BUFFER_LEN)

оставаться в пределах loop(), а уже при выполнении условия посылать данные по UART и выходить из loop()

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
1YHAIhwx    3
void loop() {
  while(true) {
    if(i == BUFFER_LEN) {
      detachInterrupt(ARDUINO_MICRO_INTTERRUPT_ON_PIN3);
      for(int x = 1; x < BUFFER_LEN; ++x) {
          Serial.print(periods[x]);
          Serial.print(" ");
       }
        Serial.println();
        Serial.flush();
        lastMicros = 0;
        delay(1500);
        i = 0;
        attachInterrupt(ARDUINO_MICRO_INTTERRUPT_ON_PIN3, sensorInterruptHandler, CHANGE);
    } else {
      if(!isRunning) {
        continue; 
      }
      byte oldSREG = SREG;
      noInterrupts ();
      mcs = micros();
      periods[i] = mcs - lastMicros;
      lastMicros = mcs;
      ++i;
      SREG = oldSREG;
    }
    isRunning = false;
  }
}

Нет, это не помогло. Также стал заполнять массив периодов с отключенными прерываниями. Притом даже если я просто буду печатать в UART текущее значение микросекунд, видно, что иногда между соседними значениями проскакиевает большой промежуток (более 3мс). Не понимаю, откуда они берутся.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Yurkin2015    290

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

оставить Ваш первый вариант, только увеличить и сделать массив достаточного размера BUFFER_LEN для записи всех шести входных пакетов. И только после записи всего, что нужно, уже тогда спокойно отправлять данные по UART.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
1YHAIhwx    3

Уже пробовал, результат аналогичен. Обновление арудиноиде тоже не спасло. Инициализация UART уже после отправки данных не помогла тоже. Девятый и десятый отчёт всё равно периодически становится равным ~1300 мкс вместо положенных 400-900.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Yurkin2015    290

Ну, тогда старым казацким способом: записывать длительность прямо в прерывании

void sensorInterruptHandler() {
    mcs = micros();
    periods[i] = mcs - lastMicros;
    lastMicros = mcs;
    ++i;
}

а в loop() проверять i == BUFFER_LEN  и отправлять по UART когда наберётся нужное число байтов.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
1YHAIhwx    3

А причина-то очевидна - с micros() всё в порядке, ровно как и с кодом. Таки дело в пульте. Я подключил фотоприёмник вместо микрофона ещё раз и настрелял десятки последовательностей. Да, пульт иногда производит импульс 9 и 10 в ~1300 мкс вместо ~900. Просто в первый раз я очень удачно нащёлкал и в запись такие последовательности не попали. И последняя чиселка тоже вполне объяснима: пульт пакет передал, встал на паузу, затем снова передавать начал, я же прерывание на изменение логического уровня повесил, вот он длину пребывания на выходе лог. 0 и считал.

Таким образом:

- с ардуиной и функцией micros() всё в порядке;

- код работает удовлетворительно;

- неправильная постановка эксперимента ведёт к потере времени.

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

const int LED_PIN = 13;
const int LED_PIN_CARRIER = 12;

void setup() {
  pinMode(LED_PIN, OUTPUT);
  pinMode(LED_PIN_CARRIER, OUTPUT);
}

void loop() {
  tone(LED_PIN_CARRIER, 38000);
  while(true) {
    delay(10);
    digitalWrite(LED_PIN, 0);
    delay(10);
    digitalWrite(LED_PIN, 1);
  }
}

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Ваша публикация должна быть проверена модератором

Гость
Вы не авторизованы. Если у вас есть аккаунт, пожалуйста, войдите.
Ответить в тему...

×   Вставлено в виде отформатированного текста.   Восстановить форматирование

  Разрешено не более 75 смайлов.

×   Ваша ссылка была автоматически встроена.   Отобразить как ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

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

Загрузка...

  • Похожие публикации

    • Автор: hardbar
      Всем обладателям Интернет ТВ от Укретелекома огромный привет. 
      Диплом все дела, 4 курс, практика на которую не ходит никто. Ливнул с универа к родителям  домой и сразу же задание "ты ж там программировал че то там как то там, прошей  MAG 255 под Aura HD".
      Вот наш MAG:

      Гугль в помощь один вечер , накопал много разбросанной инфы. 
      Вот основная: 
      Тут норм 1 и 2 стрим. Достаточно чтоб прошить самому. 

      Вот тут инфа по прошивке 25 серии через ардуино, ибо ленивый человек ищет что есть под рукой, а не покупает готовое. 
      Нюанс питание берем от +3.3В. В программе которой пишем и читаем ставить размер в 1 милион, а не 8 как я вычитал в даташите на даную память. (ибо не сможем именить прогой дамп "БИОСА" для обратной заливки)
       Я юзал Arduino NANO made krivoi Kitay. Заработало сразу.
       
    • Автор: nikdemars
      Собрал чпу станок

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

      мозг станка набор ардуино cnc с прошивкой grbl

      управляю через UniversalGcodeSender и GRBLController, они прошивку определяют, команды шлют, моторы вначале команды делают микрошаг, потом стоят как парализованные пока программа не перестает давать команды, греются.
      моторы 42BYGH47-401A:
      Характеристики:
      - напряжение питания от 5 до 24 Вольт;
      - максимаьный ток при 24В - 1.5 Ампер;
      - угловой шаг 1.8°;
      - крутящий момент при 24В - 5.5 кг.см; 
      -  сопротивление 1.6  ;
      - индуктивность 2.8 mH ;

      по ходовой вопрос, у мотора обмотки А+ черный, А- зеленый, В+ красный, В- синий (из документации о моторе)

      на плате у драйвера есть распиновка 1В,1А,2А,2В, это получается зеленый,черный,красный,синий?
       
    • Автор: MDobroch
      Доброго времени суток уважаемые форумчане!
      Обращаюсь по такому вопросу, собираю схему генератора звука на Arduino основываясь на следующей статье : http://www.instructables.com/id/Arduino-Audio-Output/
      Данная схема призвана сформировать синусоидальный сигнал определенной частоты используя 8 цифровых выходов Ардуино,  Собранном на резисторах ЦАП, фильтре и паре операционных усилителей. К сожалению в данной теме указано, что качество сигнала при использовании резисторов намного ниже чем при использовании 8 битного ЦАПа в формате готовой микросхемы. Также данное решение разрабатывалось для работы с 1 частотой. 
      Техническое задание :
      Необходима схема, работающая на двух частотах. Стабильность частоты, ровно как и качество сигнала на выходе -  крайне важны !!!   Потребителем данного сигнала будут 2 телефона подключенные к этому "генератору" посредством двух аудио кабелей. 
      Проблема:
      К сожалению я не сильно опытен в схемотехнике - являюсь программистом. Но данное решение необходимо разработать для одного проекта.
      Вопрос:
      1) Как по вашему мнение усложнится схема, для выполнения технического задания описанного выше?
      2) Какие компоненты необходимо добавить в схему? (Какую модель ЦАП нужно выбрать?)  
      3) Возможна ли вообще выдача стабильной частоты на 2 телефона при помощи ардуино или лучше выбрать для реализации данного задания другую платформу?
      4) Возможно среди форумчан есть желающие разработать подобное решение за не разумное материальное вознаграждение? Данный вариант тоже можем обсудить. 
       
      Благодарю за ответы и желаю хорошего дня!
    • Автор: Whitefoot
      Добрый день. Собрал лазерный сигнализатор задевания сетки для игры в пинг-понг теперь хочу пойти дальше и сделать дисплей для вывода счета. Иначе приходится считать все самому, а если кто-нибудь придет и отвлечет, так счет сразу из головы вылетает. Хочу сделать все как можно проще, но при этом чтобы не было примитивно. У меня есть запысы плат Arduino Nano V3 328 16M 5V CH340G, которые я как-то по распродаже заказывал из китая, потому хочу использовать одну и приделать к ней дисплей. Пока думаю в двух направляниях. 1й - купить где-нибудь на авито сломаный планшет с целым экраном, достать дисплейный модуль и переделать его для работы с ардуиной. 2й - собрать из всетодиодов большой экран на 4 цифры, каждая цифра по 7 сегментов. Вопрос у меня по второму варианту. Подскажите пожалуйста схемы подобных дисплеев. Еще желательно чтобы упраление шло по I2C интерфейсу, чтобы кучу выводов не задйствовать, но можно и более примитивно. Спасибо.
  • Сообщения

    • Синтепон напихан, это не выход, там объема нужно в два раза больше... А вот тут можно обмозговать... Есть магнит от 75гдн, он из пары блинов, попробовать их разделить, и приклеить по одному на каждый дин. Поксиполом нормально будет?
    •  вот пожалуйста на китайском сайте такие же как у вас только написано Полипропилен
    • 2) в описании ни у каких потенциометров не указана характеристика 3)проходными посчитал с7 ,с10, с20, с22, с24, с26, с29
    • Если сделать по предложенному варианту появляется две проблемы: - уровень входного сигнала звуковух (тех что я видел) в районе 2х вольт rms. На прямую нельзя, необходим делитель на входе. - получается замкнутый контур земли - ток с выхода усилителя по сигнальному проводу идет на нагрузку 4 ома, далее идет по общему проводу  обратно в усилитель - замкнутый контур как и положено, НО общий провод усилителя идет еще на вход звуковой карты, на которой обычно земли входов и выходов соединены и далее общий провод идет на вход усилителя по общему проводу сигнальной цепи, а в усилителе сигнальная земля соединена с  силовым общим проводом (иногда ставят в усилителе 10 ом между сигнальной землей и силовой). в итоге появляется второй контур для протекания тока и распределение токов получится пропорционально сопротивлению проводов силового сигнального от нагрузки и сигнального по описанному контуру. например силовой общий от усилителя к нагрузки имеет сопротивление  при длине 2 метра и сечении 2,5 мм кв примерно 0,02*2/2,5=0,016 ом (). Ток в нем при напряжении на выходе усилителя 14 вольт -  14/4 ом нагрузки=3,5 ампера. Падение напряжения на общем силовом проводе (провод от усилителя к нагрузке 4 ом) =3,5*0,016=0,056 вольта. Это напряжение прикладывается к сигнальному общему проводу, идущему от точки соединения общего силового с нагрузкой 4 ома , через вх/выходной разъем звуковухи, до входа усилителя (и далее к кусочку проводника соединяющего входной общий с общим блока питания или если там установлен резистор 10 ом, то через него). Предположим длина этого провода 2 метра, что получается, пусть провод будет витой парой в экране и минус идет не через экран (он землится в одной точке с одной стороны), а через один из проводов витой пары. Возмем сечение 0,35 мм кв. Сопротивление этого проводника 0,02*2/0,35=0,114 ом. В нем будет течь ток 0,056/0,114=0,49 АМПЕРА. Если экран соединить с двух сторон, сопротивление цепи уменьшится и ток еще больше возрастет. Эти 0,49 ампера создадут падение напряжение на общем сигнальном проводе, которое грубо говоря "пролезет" на сигнальный вход усилителя за счет падения напряжений на участках цепи сигнального общего провода. В таких условиях ни о какой достоверности результатов и речи быть не может. По этой причине необходим балансный вход , т.е. чтобы не было связи по общему проводу между входом и выходом звуковой карты. Другого внешнего цапа у нас нету, поэтому приходится выкручиваться с этим, но есть подозрение, что у него не "все чисто" внутри касательно развязки земли.  
    • Добавить вату в ас,если возможно добавить магнит(приклеить отталкивающей стороной) конешно ачх на средних может изменится
    • Всем привет! Помогите подключить провода на место. Вытяжка Bosch DKE 955 D. На первом фото провода которые нужно подключить, в левой руке от блока кнопок (синий, красный, серый), а в правой от двигателя (красный, коричневый, заземление). Места куда все эти провода подключаются на втором (кабель питания) и третьем (пусковой конденсатор) фото. Буду благодарен, все что больше трех проводков вызывает шок и удивление.
    •  Так как луче поступить?