Хочу простого. Считать PWM со входа и по результатам считанного заставить диод гореть, выключится, или мигать.

Saradon
Offline
Зарегистрирован: 17.12.2015

Скажу сразу, в програмировании - как свинья в апельсинах. Ничего не понимаю.
но хотелось-бы, всё-же, не найти исполнителя, а пусть и с чужой помощью, но сделать самому, с пониманием.
Аваимодельный приёмник на канале выдаёт PWM сигнал.
Хотел-бы разделить диапазон (0-255, или же 900-2000 ??) на три сектора.
При первой трети диод выключен, при второй - мигает, при третей - горит постоянно.
Однако так нигде ничего и не смог найти относительно того, как читать PWM сигнал со входа.
Единственное, на что меня хватило - это вот на это:
 

// Функция void setup запускается один раз после подачи питания
void setup() {
  int LED = 13;             // пин 13 называем LED
  int PWM = 10;             // пин 10 назывfем PWM
  pinMode(LED, OUTPUT);     // инициализируем цифровой пин 13 как выход.
  pinMode(PWM, INPUT);      // инициализируем цифровой пин 10 как вход
}

// Функция void loop запускается на бесконечное циклическое выполнение
void loop() {
  if (digitalRead(PWM) < 38){  // если значение PWM меньше 38 выполнить выключение
  digitalWrite(13, LOW);    // выключить LED (устанавливаем минимальный вольтаж - LOW)
  }
  else if (digitalRead(PWM) > 187) {  // если значение PWM больше 187 выолнить включение
  digitalWrite(LED, HIGH);   // включить LED (устанавливаем максимальный вольтаж - HIGH)
  }
  else {                    // если значение PWM больше 1117 и меньше 1980 выолнить мигание
  digitalWrite(LED, HIGH);   // включить LED (устанавливаем максимальный вольтаж - HIGH)
  delay(10);                // выжидаем паузу (1000 миллисекунд = 1 секунда)
  digitalWrite(LED, LOW);    // выключить LED (устанавливаем минимальный вольтаж - LOW)
  delay(10);                // выжидаем паузу (1000 миллисекунд = 1 секунда)
  digitalWrite(LED, HIGH);   // включить LED (устанавливаем максимальный вольтаж - HIGH)
  delay(10);                // выжидаем паузу (1000 миллисекунд = 1 секунда)
  digitalWrite(LED, LOW);    // выключить LED (устанавливаем минимальный вольтаж - LOW)
  delay(1000);              // выжидаем паузу (1000 миллисекунд = 1 секунда)

Понимаю, что это глубоко не правильно, но я в тупике.

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

Цитата:Понимаю, что это глубоко не правильно, но я в тупике.

(анекдот) 
-Доктор! Почему когда я бью головой об стену у меня голова начинает болеть.
- @_@

Ответ по теме PWM не предназначена для передачи данных.

 

 

ЕвгенийП
ЕвгенийП аватар
Онлайн
Зарегистрирован: 25.05.2015

Эта задача значительно сложенее, чем то, что может сделать человек, не умеющий программировать вообще, даже с посторонней помощью.

Так что либо заказывайте, либо начинайте серьёзно изучать программирование. Тогда через несколько месяцев напишете сами.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Скажу по секрету: digitalRead() потому и называется digitalRead, что читает цифровой сигнал: 0 или 1. Поэтому и в строке 11, и в строке 14 результат сравнения предрешен, - программу можно подсократить.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015
Saradon, кстати, если после Вашего PWM стоит интегрирующая цепь, можно действительно воспользоваться советом Калапуция, и тогда задача существенно упрощается.
p.masyukov
p.masyukov аватар
Offline
Зарегистрирован: 14.11.2015

ЕвгенийП пишет:

Эта задача значительно сложенее, чем то, что может сделать человек, не умеющий программировать вообще, даже с посторонней помощью.

Так что либо заказывайте, либо начинайте серьёзно изучать программирование. Тогда через несколько месяцев напишете сами.

Если в школе нормальной учился, позможно там рассказывали основы программирования типа басик и т.п.

Амперку ролики посмотрит и через неделю напишет - если конечно захочет понять, что и как.

Saradon
Offline
Зарегистрирован: 17.12.2015

ЕвгенийП пишет:

Эта задача значительно сложенее, чем то, что может сделать человек, не умеющий программировать вообще, даже с посторонней помощью.

Так что либо заказывайте, либо начинайте серьёзно изучать программирование. Тогда через несколько месяцев напишете сами.

Это я уже понял. На первый взгляд всё казалось просто. Arduino может генерировать PWM, но читать его напрямую, оказывается, не умеет.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Saradon пишет:

Это я уже понял. На первый взгляд всё казалось просто. Arduino может генерировать PWM, но читать его напрямую, оказывается, не умеет.

Ну да.

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

А еще компьютер легко переводит из *.mid в *.wav или *.mp3, а обратно - никак.

Я Вам больше скажу: левую часть равенства (2+3)*(6-1)=25 преобразовать в правую может даже школьник, а вот из правой получить левую еще никому не удавалось.

Странно, что такие вещи до сих пор вызывают удивление.

Saradon
Offline
Зарегистрирован: 17.12.2015

p.masyukov пишет:

Если в школе нормальной учился, позможно там рассказывали основы программирования типа басик и т.п.

Амперку ролики посмотрит и через неделю напишет - если конечно захочет понять, что и как.

У нас в школе стояли Корветы востмибитные, а преподавательница была уверена, что жёсткий диск - это дискета 3,5. А дискета 5,25 - это гибкий диск. Я не утрирую!

Пытался освоить хотя-бы азы Ардуино - не даётся она мне. Так-же, как и иностранные языки.  С логикой, вроде, проблем нет, а вот в переменных и функциях всяких теряюсь.

На Амперке нашел подходящий скетч под мои запросы, надо только подправить. Но пока я в нём понимаю мало чего. Буду пробовать разобраться.

http://forum.amperka.ru/threads/rc-передатчик-и-arduino-uno.1244/

MacSim
Offline
Зарегистрирован: 28.11.2012

а что вы подразумеваете под:

(0-255, или же 900-2000 ??)

количиство "тиков" в секунду? зачем так усложнять считая их все? двух из них вполне достаточно

да... Задача стоит одна, программу написали под другую, пример от амперки вообще не рядом.

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

ssss
Offline
Зарегистрирован: 01.07.2016

Saradon пишет:

Это я уже понял. На первый взгляд всё казалось просто. Arduino может генерировать PWM, но читать его напрямую, оказывается, не умеет.

Подобная тема где-то на казусе проскакивала.  Там правда была мега без ардуины.

На СТМ8 или СТМ32 подобное так вообще влёгкую, аппаратно. На Хмеге тоже, если память не изменяет. Ну и на некоторых новых ПИКах.

negavoid
Offline
Зарегистрирован: 09.07.2016

andriano пишет:

А еще компьютер легко переводит из *.mid в *.wav или *.mp3, а обратно - никак.

Вы не поверите :))) http://www.ofoct.com/audio-converter/convert-wav-or-mp3-ogg-aac-wma-to-midi.html хоть и понятно, что сигнал обратно в ноты не разложить. Да и файнридер в последнее время творит просто чудеса :) Скоро и до разложения на множители доберутся, я на это искренне надеюсь, долой устаревшую криптографию :)))
andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

negavoid пишет:

Вы не поверите :))) http://www.ofoct.com/audio-converter/convert-wav-or-mp3-ogg-aac-wma-to-midi.html хоть и понятно, что сигнал обратно в ноты не разложить. Да и файнридер в последнее время творит просто чудеса :) Скоро и до разложения на множители доберутся, я на это искренне надеюсь, долой устаревшую криптографию :)))

Вот так и знал, что кто-то что-то подобное обязательно вставит.

Вы попытайтесь им разложить оркестровку.

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

strarbit
Offline
Зарегистрирован: 12.06.2016

Можете посмотреть на самом лучшем форуме тему:

Пультоскоп на Arduino 27МГц!!!  

olegtur77
Offline
Зарегистрирован: 09.04.2015

Тут речь не о самом ШИМ, а о канальном импульсе, стандартном для систем радиоуправления. Для этой цели есть простая функция PulseIn - считывает длительность и возвращает данные в микросекундах, а дальше как говориться дело за малым. Пример есть как в среде, так и на сайте в уроках.

 

MacSim
Offline
Зарегистрирован: 28.11.2012

olegtur77 пишет:

Тут речь не о самом ШИМ, а о канальном импульсе, стандартном для систем радиоуправления. Для этой цели есть простая функция PulseIn - считывает длительность и возвращает данные в микросекундах, а дальше как говориться дело за малым. Пример есть как в среде, так и на сайте в уроках.

 

а ктож его знает когда его ждать. ждать можно долго.... лучше уж на прерывание внешнее завести... и далее мерить

olegtur77
Offline
Зарегистрирован: 09.04.2015

Ждать ничего не надо, РРМ-сигнал - идет длительностью 1-2мс с периодом 20мс, поэтому и ждать не прийдется. Я таким путем решил. У меня другая проблемка, с компиляцией проги под тини13 с применением стандартной библиотеки servo.

 

MacSim
Offline
Зарегистрирован: 28.11.2012

olegtur77 пишет:

Ждать ничего не надо, РРМ-сигнал - идет длительностью 1-2мс с периодом 20мс, поэтому и ждать не прийдется. Я таким путем решил. У меня другая проблемка, с компиляцией проги под тини13 с применением стандартной библиотеки servo.

 

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

думаю библиотека использует то, чего в тини нет. посмотрите *.h && *.cpp файлы

olegtur77
Offline
Зарегистрирован: 09.04.2015

Я взял за основу пример sweep, с 328й работает. Почитал что у тини13 8битный таймер, а у 328й 16бит. на это и ругается компилятор. А как переделать, пока не могу въехать. На слабом англиском понял нашел что есть другая библиотека  servo8bitб но как ее "пришить" не разобрался еще.

Программа аналогична авторской задумке, только у меня в зависимости от длительности вх имп меняется частота sweep (перекладка сервы).

вот код

// Sweep
#include <Servo.h> 
#define RCIN 3 // вход РРМ
Servo myservo; 

int pos = 90;    // установка сервы в нейтраль
void setup() 
{ 
  pinMode(RCIN, INPUT); 
 
  myservo.attach(2);  // серва подключена на выход 2
} 
 
 
void loop() 
{ 
  int pos;
  int pwm;
  pwm = pulseIn(RCIN, HIGH, 20000);
  if (pwm > 1200 & pwm < 1900) {
    for (pos = 0; pos < 180; pos += 1) {
      myservo.write(pos);
      delay(abs(((2500 - pwm) / 200) - 1)); // сдесь меняется скорость например пвм 1000 2000-1000/200 получаем задержку 5мс умножаем на 180 и имеем около секунды, 2000-2000/

  } 
  for (pos = 180; pos >= 1; pos -= 1) {
      myservo.write(pos); //тоже самое
      delay(abs(((2500 - pwm) / 200) - 1));

    }
     
} 
else 
   myservo.write(90);              // если за переделами ,  серва в нейтраль 
    delay(15);  
}

 

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

удалено

Yarik.Yar
Offline
Зарегистрирован: 07.09.2014

Товарисч olegtur77, вы PWM с PPM-то не путайте.  В режиме PPM все данные всех каналов передаются по одному проводу, в режиме PWM - наш любимый сигнал 50Гц (333Гц для цифровых серв/регулей,etc) с заполнением от ~600нс до ~2000нс, судя по вашему коду, у вас именно PWM.

А то ТС бросится гуглить и погрязнет в бездне.

P.S. Настроить таймер для сервового ШИМа можно даже без библиотеки. Это не сложно, я гарантирую это)

 

Тарас Петрович
Offline
Зарегистрирован: 21.11.2015

Если частота ШИМа известна, задача упрощается. Заводить сигнал на внешне прерывание по фронту, в обработчике пускать таймер с удобным предделителем частоты и переключать прерывание на спад. В обработчике прерывания по спаду, останавливать таймер, пересчитывать значение счётных регистров таймера в удобные единицы, таймер обнулять, переключать прерывание на фронт. Я думаю так. Вот если частота ШИМа не известна- тут сложнее, сначала её придётся подсчитать.

olegtur77
Offline
Зарегистрирован: 09.04.2015

Yarik.Yar пишет:

Товарисч olegtur77, вы PWM с PPM-то не путайте.  В режиме PPM все данные всех каналов передаются по одному проводу, в режиме PWM - наш любимый сигнал 50Гц (333Гц для цифровых серв/регулей,etc) с заполнением от ~600нс до ~2000нс, судя по вашему коду, у вас именно PWM.

Извиняюсь за это дикое упрощение терминов. Не первый год в теме :) Просто отношение к ШИМ - многосторонее...А для канальных импульсов, которые относятся именно к радиуправлению,  уже изначально определены параметры, и их необязательно угадывать или ждать. Может сумбурно выразился..Решал задачу как получалось, счел наиболее простым решением, поэтом и посоветовал ТС такое же. На 45й тине работает, а вот с 13й пока не получилось. Не работает эта функция

Опять же :

Saradon пишет:

Хотел-бы разделить диапазон (0-255, или же 900-2000 ??) на три сектора.
При первой трети диод выключен, при второй - мигает, при третей - горит постоянно.
Однако так нигде ничего и не смог найти относительно того, как читать PWM сигнал со входа.

Чего просил автор

olegtur77
Offline
Зарегистрирован: 09.04.2015

Вот програмка управления зумом камеры на самолете,по протоколу Pelco-D, которуя переписал взамен штатной. Вней использовал оператор pulseIn , так же можно и по желанию ТС сделать любой свич на любое(в разумных пределах) переключений. За код прошу не пинать, нужно было устройство срочно, разбираться в красивости кода некогда, да и незачем было.

int pin = 2; //назначаем вход D2 
  
  byte outp[] = { 0x80, 0x01, 0x04, 0x07, 0x02, 0xFF, 10, 13 }; // команда зумм+
  byte outm[] = { 0x80, 0x01, 0x04, 0x07, 0x03, 0xFF, 10, 13 }; // команда зумм-
  byte outn[] = { 0x80, 0x01, 0x04, 0x07, 0x00, 0xFF, 10, 13 }; // команда зумм стоп
  unsigned long ppm ; // объявляем переменную ррм - длительность входного импульса
  void setup()
    {
      Serial.begin(9600); //скорость порта
      pinMode(pin, INPUT); //пин 2 - это вход
}
 
    void loop()
{
    ppm = pulseIn(pin, HIGH); // прерывание с положительнвм фронтом, переменная ррм-входной импульс в микросекундах
 if (ppm < 1300)              //1-е условие сравнения
 {
    for(int i = 0; i < 7; i++) 
    {
        Serial.write(outm[i]);  //вывод массива в порт
    }    
 }
 else if (ppm > 1700)        //2-е условие сравнения
 { 
  for(int i = 0; i < 7; i++)
    {
        Serial.write(outp[i]);  //вывод массива в порт
    }    
 }
 else
 {
  for(int i = 0; i < 7; i++)    //3-е условие сравнения
    {
        Serial.write(outn[i]);  //вывод массива в порт
    }    
 }
 }     

 

a5021
Offline
Зарегистрирован: 07.07.2013

Тарас Петрович пишет:
Если частота ШИМа известна, задача упрощается.

Да нет большой разницы, известна или не известна. Настраиваем пин, чтобы при изменении состояния на нем генерировалось прерывание. В обработчике вызываем millis(). Трех сохраненных таким образом значений, возвращаемых функцией millis(), будет достаточно, чтобы узнать и период и коэффициент заполнения ШИМ-сигнала. Это, если не хочется использовать таймер в режиме захвата, а так, конечно, точные параметры ШИМ-а удобнее определять именно таймером.

Тарас Петрович
Offline
Зарегистрирован: 21.11.2015

a5021, а миллис в прерывании виден?

a5021
Offline
Зарегистрирован: 07.07.2013

А какие имеются предпосылки, чтобы считать иначе?

Saradon
Offline
Зарегистрирован: 17.12.2015

Спасибо всем.
В общем, программирование - это не моё.
Проще будет взять полный проект MultiWii, где эта моргалка уже встроена и просто переназначив порты использовать уже её.
Получается, будет задействовано 0.1% от всего таскаемого кода :)

MacSim
Offline
Зарегистрирован: 28.11.2012

Saradon пишет:

Спасибо всем.
В общем, программирование - это не моё.
Проще будет взять полный проект MultiWii, где эта моргалка уже встроена и просто переназначив порты использовать уже её.
Получается, будет задействовано 0.1% от всего таскаемого кода :)

Однозначно верно. Если не твое то лучше купить готовое или заказать разработку тем у кого  программирование - это моё. Можете воспользоваться темой "ищу исполнителя". Там помогут.