Как правильно считывать PWM?
- Войдите на сайт для отправки комментариев
Добрый день!
Требуется помощь! Не считываются показания цифрового компаса.
Имеется:
- Arduino Uno SMD (www.megachip.ru/item.php)
- IO Expansion Shield For Arduino(V5) (www.dfrobot.com/index.php)
- Цифровой компас CMPS-03 (www.inexglobal.com/products.php)
Компас может отдавать значения по интерфейсам l2c и PWM.
Пытаюсь считать значения PWM.
Из документации:
The PWM signal is a pulse width modulated signal with the positive width of the pulse representing the angle.
The pulse width varies from 1mS (0° ) to 36.99mS (359.9° ) – in other words 100uS/° with a +1mS offset. The
signal goes low for 65mS between pulses, so the cycle time is 65mS + the pulse width - ie. 66ms-102ms. The
pulse is generated by a 16 bit timer in the processor giving a 1uS resolution, however I would not recommend
measuring this to anything better than 0.1° (10uS). Make sure you connect the I2C pins, SCL and SDA, to the
5v supply if you are using the PWM, as there are no pull-up resistors on these pins.
Компас подлключен на цифровой порт 3. Проблема в том , что на вход всегда идет "1".
Проверял следующим кодом:
const int pwm_pin = 3;
int pwm_val = 0;
int pwm_val_t = 0;
void setup() {
Serial.begin(9600);
pinMode(pwm_pin, INPUT);
}
void loop() {
pwm_val=digitalRead(pwm_pin);
//if (pwm_val=0) pwm_val_t= pulseIn(pwm_pin, HIGH ) ;
if ( pwm_val=0) Serial.print(0); ;
//Serial.println();
//delay(200);
}
Что я не так делаю ?
digitalRead всегда будет возвращать High или Low
Вам нужен похоже PulseIn чтобы считать длину сигнала
Я и начал с PulseIn, см. закомментаренный код.
Мне кажется, что на вход всегда идет HIGH , хотя LOW так же должен иди.
А с подключением компаса к ардуине все в порядке? Что-то вроде этого?
(Схема расположена на http://www.robot-electronics.co.uk/htm/cmps2pwm.shtml)
Вообщето ШИМ считывать надо аналоговым портом. А учитывая вот это: Make sure you connect the I2C pins, SCL and SDA, это Аналоговые 5 SCL и 4 SDA.
Вообщето ШИМ считывать надо аналоговым портом.
ШИМ-сигнал с пина 4 упоминаемого здесь компаса - это импульсы шириной 1-37 мс, выдаваемые с периодичностью 65 мс (www.robotstorehk.com/CMPS03_release.pdf). Задача именно для цифрового порта и таймера (вся соответствующая программная требуха зашита в логике PulseIn), а не для АЦП. Конечно, если по пути сигнала какую-нибудь интегрирующую цепочку соорудить, то можно и АЦП воспользоваться, но это как гланды через ж... вырезать.
А вот пины 2-3 (SDA-SCL) подтянуть к плюсу следует попробовать - где-то мне такой эскизик именно в контексте снятия PWM-сигнала с данного компаса попадался...
Кстати, и на приведенной мной схеме соответствующая рекомендация в виде текста имеется - "connect 2x47 Resistors from pins 2&3 to Vcc"
Ну если импульсы надо, то можно через прерывания, тоесть импульс ХАЙЖ - прерывание запустилось и отсчитывает втемя через таймер в переменную пока импульс не ЛОУ. Но имхо I2C удобнее будет, к ней даже библиотека в стандартном комплекте дуины есть (ware). Резисторы от 4К7 от SCL и от SDA на +5 для подтяжки линий к ХАЙ, но по идее пулап резисторы должны уже стоять.
... по идее пулап резисторы должны уже стоять.
По идее - может быть и да. По даташиту - нет:
"Make sure you connect the I2C pins, SCL and SDA, to the 5v
supply if you are using the PWM, as there are no pull-up resistors on these pin"
Ну, топикстартер, похоже, выводы ардуины экономит...
Кстати, его что-то не слышно совсем.
Ау, ТС!!! Удалось добиться передачи информации по PWM-каналу или нет???
А чем же PulseIn не подходит?, ждет начало сигнала и возвращает его длину в микросекундах, это ж то, что надо? или я что-то упускаю? ТС загадочно сказал, что у него закомменчено PulseIn, но почему закомменчено не ясно.
ТС загадочно сказал, что у него закомменчено PulseIn, но почему закомменчено не ясно.
Как сказано в самом первом сообщении, его "проблема в том, что на вход всегда идет "1"". В таких условиях PulseIn просто не сработает - ведь на входе всегда HIGH.
По поводу правильности подключения: шилд распаяный уже
http://www.inexglobal.com/products.php?type=addon&cat=app_sensors&model=...
трудно ошибиться, разъемы стандартные
По поводу подключения по I2C: у меня под рукой проводочков нужных нету :-(, да и хотелось разобраться с PWM/
Кроме варианта с кривыми руками , у меня еще есть следующие варианты:
Грешу все же на IO Expansion Shield For Arduino(V5), т.к. если подключаю кнопку http://www.megachip.ru/item.php?item_id=2466000 то в нажатом состоянии с нее приходит сигнал "0", а в состоянии покоя "1".
ТС загадочно сказал, что у него закомменчено PulseIn, но почему закомменчено не ясно.
Как сказано в самом первом сообщении, его "проблема в том, что на вход всегда идет "1"". В таких условиях PulseIn просто не сработает - ведь на входе всегда HIGH.
Все верно , т.к. PulseIn давал "0", я его закоммитил , что бы разобраться в чем дело.
У вас соединены четыре платки в кучу - компас, переходная плата для компаса, IO Expansion Shield и Arduino?
И все без "проводочков"?
Хотелось бы взглянуть на фото собранной конструкции.
а на прямую без IO Expansion Shield пробовали подключать?
а на прямую без IO Expansion Shield пробовали подключать?
не прбовал, видимо нужно это сделать, но нет под рукой проводов.
а на прямую без IO Expansion Shield пробовали подключать?
не прбовал, видимо нужно это сделать, но нет под рукой проводов.
Первое: паяльника тоже нет? Раздербанить какую-нибудь старую мышку или клаву, кусок витой пары, нарезать оттуда проводков, оголить/залудить концы - и можно прекрасно выполнять временную коммутацию через мама-разъемы ардуины и представленного на фотографии тройного шлейфика.
Второе: у вас светодиодик свободный найдется? Попробуйте подключать его к выводам компаса, переходной платки и т.д. и следить за изменением яркости свечения и частоты мигания (от 10 до 15 Гц) при повороте компаса.
Третье:судя по нижней фотографии на страничке компаса (www.inexglobal.com/products.php), Vcc подается на дальний от кромки платки пин (зеленый проводок на вашей фотографии). А у IO-шилда Vcc находится ровно посередине (красный проводок). У вас есть схема разводки переходной платки? Уточните, пожалуйста, за что отвечает каждый из трех выводов PWM-разъема (на переходной платке). Ибо если мои подозрения верны, то на третий цифровой порт подается Vcc, то есть там всегда присутствует неизменный жирный HIGH - в полном соответствии с описываемыми симптомами.
PS: кстати, и на компас в этом случае подается черти что, а не питание...
Первое: паяльника тоже нет? Раздербанить какую-нибудь старую мышку или клаву, кусок витой пары, нарезать оттуда проводков, оголить/залудить концы - и можно прекрасно выполнять временную коммутацию через мама-разъемы ардуины и представленного на фотографии тройного шлейфика.
Да. надо подключить на прямую.
Третье:судя по нижней фотографии на страничке компаса (www.inexglobal.com/products.php), Vcc подается на дальний от кромки платки пин (зеленый проводок на вашей фотографии). А у IO-шилда Vcc находится ровно посередине (красный проводок). У вас есть схема разводки переходной платки? Уточните, пожалуйста, за что отвечает каждый из трех выводов PWM-разъема (на переходной платке). Ибо если мои подозрения верны, то на третий цифровой порт подается Vcc, то есть там всегда присутствует неизменный жирный HIGH - в полном соответствии с описываемыми симптомами.
Зеленый проводок это +5V, как раз на фото видно , что дорожка идет к разъему , а рядом видно надпись на плате "5V"
Красный провод - это PWM(Pin 4 на плате компаса)
Черный GND
Я вот думаю , м.б. компасу питания не хватает ? С цифрового вывода 5V должно идти ?
Ну вот, похоже, что-то проясняется. В стандартных шлейфах PWM-приводов (сервомашинки и прочая дребедень) линии располагаются в следующем порядке:
- масса (обычно черный)
- плюс (или Vcc) (обычно красный)
- сигнальная линия (белый или желтый)
Кстати, именно так эти выводы на используемой вами части IO Expansion Shield промаркированы (Gnd-Vcc-Signal или что-то там)
у вас же на переходной плате Gnd-Signal-Vcc - две линии в обратном порядке.
Так что - покопайте в эту сторону.
Ну вот, похоже, что-то проясняется. В стандартных шлейфах PWM-приводов (сервомашинки и прочая дребедень) линии располагаются в следующем порядке:
- масса (обычно черный)
- плюс (или Vcc) (обычно красный)
- сигнальная линия (белый или желтый)
Кстати, именно так эти выводы на используемой вами части IO Expansion Shield промаркированы (Gnd-Vcc-Signal или что-то там)
у вас же на переходной плате Gnd-Signal-Vcc - две линии в обратном порядке.
Так что - покопайте в эту сторону.
Действительно. На стандартных разъемах от Inex, Signal и Vcc идут в другом порядке.
После того как сделал правильный порядок проводов все заработало.
step962, спасибо большое за помощь!
if ( pwm_val=0)
эквивалентно
if ( false )
надо написать if ( pwm_val == 0)
Есть вопрос так же по ШИМ. Arduino Una
pulseln() не предлагать.
У меня на порты приходят 5 каналов с ШИМ.
самый быстрый я повесил на 2 пин, остальные повесил на 3 пин. с 4 датчиков приходит сигнал в порт, и через диоды от всех на 3 пин. И по прерыванию опрашиваю порт. Вопрос, в ниже я привожу свой код и там два варианта. Опроса один закоменчен.
И тот и тот работает, но мне не нравится как работают. Мне кажется я, не очень красиво написал их. На прерывание на 3 пин не смотрите. Но если есть советы я выслушаю. На втором порту нужна полная характеристика, на 3 только частота.
void setup() { Serial.begin(230400); initPins(); //функция инициализации Pin cli();//отключаем прерывание //настройка таймера 2 TCCR2A = 0; //обнулили TCCR2B = 0; //обнулили TIMSK2 = (1 << TOIE1); TCCR2B |= (1 << CS10); //настроили без деления 255*6.25е-8 сек. attachInterrupt(digitalPinToInterrupt(rotSensor_All), isr_wheel, RISING);// актевирует срабатывания функции rotationSenaor на пине 2 изменение с 0, на 1 attachInterrupt(digitalPinToInterrupt(PWRDAT_Pin), isr_ppm, CHANGE);// актевирует срабатывания функции PWRDAT_H на пине 3 изменение с 0, на 1 sei();//разрешили прерывание PPM_status = digitalRead(PWRDAT_Pin); // текущее состояние берём из состояния пина } // Проверка void isr_ppm() { if (PPM_status & 1) { // PWR_Pulse = PWR_TIMER; // запоминаем время между импульсами PWR_TIMER = 0; // обнуляем таймер } else { // PWR_Duty = PWR_TIMER; //запоминаем время продолжительности импульса } PPM_status ^ 1; // 0b00000001 // применяем побитовый XOR, 1 такт } /* void PWRDAT_H () {//обработка начала импульса ШИМ PWR_Pulse = PWR_TIMER; // запоминаем время между импульсами PWR_TIMER = 0; // обнуляем таймер attachInterrupt(1, PWRDAT_L, FALLING);// активирует срабатывания функции PWRDAT_L на пине 3 изменение с 0, на 1 } void PWRDAT_L () {//обработка спада импульса ШИМ PWR_Duty = PWR_TIMER; //запоминаем время продолжительности импульса attachInterrupt(1, PWRDAT_H, RISING);// активирует срабатывания функции PWRDAT_H на пине 3 изменение с 1, на 0 } */ void isr_wheel () {//функция работы с датчиками по прерыванию на пине 2 (прерывание 0 ) DataRotSensor = PIND; switch (DataRotSensor & (1 << N)) { case 7: tWbl = rotSensor_back_left_Timer; rotSensor_back_left_Timer = 0; break; case 6: tWbr = rotSensor_back_right_Timer; rotSensor_back_right_Timer = 0; break; case 5: tWfl = rotSensor_front_left_Timer; rotSensor_front_left_Timer = 0; break; case 4: tWfr = rotSensor_front_right_Timer; rotSensor_front_right_Timer = 0; break; } } ISR (TIMER2_OVF_vect) { //по переполнению таймера срабатывает прерывание каждые 15 мкс rotSensor_back_left_Timer++ ;//таймер датчика вращения rotSensor_back_right_Timer++;//таймер датчика вращения rotSensor_front_left_Timer++;//таймер датчика вращения rotSensor_front_right_Timer++;//таймер датчика вращения PWR_TIMER++;//таймер длительность сигнала ШИМ }