analogWrite() на любом выводе

maksim
Offline
Зарегистрирован: 12.02.2012

Не раз уже поднималась тема о генерации ШИМа на любом из выводов или на всех выводах сразу. Написал простенькую библиотеку, которая позволяет Ардуино программно генерить 8-ми битный ШИМ на любом из выводов. Библиотека использует TIMER2, тестировалась только на Atmega48/88/168/328, то есть UnoDuemilanoveNano и т.п. 

maksim
Offline
Зарегистрирован: 12.02.2012

И так. Качаем архив, распаковываем его как обычно в ...\arduino-1.х\libraries\ , запускаем IDE, в примерах должна появиться вкладка PWM и в ней 3 примера. 

Описание функций:

analog.Frequence(SLOW);     // позволяет изменить частоту ШИМа
analog.Frequence(NORMAL);
analog.Frequence(FAST);

analog.Mode(pin, OUTPUT);   // инициализирует ШИМ на данном выводе и настраивает его на выход
analog.Mode(ALL, OUTPUT);  // инициализирует ШИМ на всех 20 выводах и настраивает их на выход
analog.Mode(pin, INPUT);      // отключает ШИМ на данном выводе и настраивает его на вход
analog.Mode(ALL, INPUT);     // отключает ШИМ на всех 20 выводах и настраивает их на вход

analog.Write(pin, val);          // все как и у стандартной функции analogWrite

analog.State(pin);               // возвращает текущее значение ШИМа

Пример:

Видео

AlexFisher
AlexFisher аватар
Offline
Зарегистрирован: 20.12.2011

Понятненько. Интересная библиотечка.

Для леонардо и меги редактируем файл pins.h согласно пин-маппингу.

maksim
Offline
Зарегистрирован: 12.02.2012

В итоге все пришло к тому, что как таковая библиотека не нужна.

Создайте в своем проекте новую вкладку с именем PWM:

и копируйте туда это содержимое:

пример кода:

P.S. #define ALL задействует все 20 выводов дуины.

AlexFisher
AlexFisher аватар
Offline
Зарегистрирован: 20.12.2011

У меги и так шимов много. Для меги имеет смысл применять только на выходы больше 20.

С другой стороны, либа позволяет высвободить таймер1 для себя :)

HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013

На 8 меге гугаетсо 

1C:\MC\arduino-1.0.4\libraries\PWM\PWM.cpp: In constructor 'PWM::PWM()':
2C:\MC\arduino-1.0.4\libraries\PWM\PWM.cpp:17: error: 'TCCR2A' was not declared in this scope
3C:\MC\arduino-1.0.4\libraries\PWM\PWM.cpp:18: error: 'TCCR2B' was not declared in this scope
4C:\MC\arduino-1.0.4\libraries\PWM\PWM.cpp:19: error: 'OCR2A' was not declared in this scope
5C:\MC\arduino-1.0.4\libraries\PWM\PWM.cpp:20: error: 'TIMSK2' was not declared in this scope
6C:\MC\arduino-1.0.4\libraries\PWM\PWM.cpp: In member function 'void PWM::Frequence(byte)':
7C:\MC\arduino-1.0.4\libraries\PWM\PWM.cpp:29: error: 'TCCR2B' was not declared in this scope
8C:\MC\arduino-1.0.4\libraries\PWM\PWM.cpp: At global scope:
9C:\MC\arduino-1.0.4\libraries\PWM\PWM.cpp:36: warning: 'TIMER2_COMPA_vect' appears to be a misspelled signal handler

А так хочется ещё пару ножек с ШИМ"мом :(

maksim
Offline
Зарегистрирован: 12.02.2012

Потому что на меге8 отсутстует таймер2.

HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013

Можно немного глупый вопрос, а первый можно задействовать?

maksim
Offline
Зарегистрирован: 12.02.2012

Конечно можно. По аналогии можете сделать, только лучше делать сразу для конкретных выводов ,тогда работать будет быстрее.

HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013

Тоесть все что имеет в тексте TCCR2A, TCCR2B, OCR2A, TIMSK2, TCCR2B, TIMER2_COMPA_vect изменить на 1 или как?

Вот бы как в дуинки уно... тоесть как в меги 328 были все ноги что поддерживают ШИМ имели поддержку у меги 8-й.

maksim
Offline
Зарегистрирован: 12.02.2012

Почти, только таймер1 16битный, а следовательно некоторые регистры состоят из младшего и старшего реистров.

Например на OCR1A компилятор ругнтся так как он 16-битный и состоит из OCR1AH и OCR1AL.

HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013

Понятно... что ничего непонятно...

Просто сменить 2-ки на 1-ки неполучилось.

Клапауций
Offline
Зарегистрирован: 10.02.2013

HWman пишет:

Понятно... что ничего непонятно...

Просто сменить 2-ки на 1-ки неполучилось.

atmega88 - не?

HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013

Я пользуюсь ATmega8A-PU.

Клапауций
Offline
Зарегистрирован: 10.02.2013

HWman пишет:

Я пользуюсь ATmega8A-PU.

Можно ведь постепенно переползать на более современные камни - по сравнению с мега8-й разницы не заметите, но присутсвуют плюшки аппаратной и программной совместимости с фирменными дуино.

HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013

Можно, но пока будут современные камни плыть из Китая перебиваться буду тем что есть.

BabaDusya
BabaDusya аватар
Offline
Зарегистрирован: 13.10.2012

Не плохо !  На меге  мне удалось максимум задействовать 14 пинов! А реально их все задействовать под "ШИМ" имея в виду 54 пина? Тут в ...\PWM\PINS изменения сделал, надеясь хотя б 32  зажечь

01#define HIGH_0  PORTD|=1<<0
02#define HIGH_1  PORTD|=1<<1
03#define HIGH_2  PORTD|=1<<2
04#define HIGH_3  PORTD|=1<<3
05#define HIGH_4  PORTD|=1<<4
06#define HIGH_5  PORTD|=1<<5
07#define HIGH_6  PORTD|=1<<6
08#define HIGH_7  PORTD|=1<<7
09#define HIGH_8  PORTB|=1<<0
10#define HIGH_9  PORTB|=1<<1
11#define HIGH_10 PORTB|=1<<2
12#define HIGH_11 PORTB|=1<<3
13#define HIGH_12 PORTB|=1<<4
14#define HIGH_13 PORTB|=1<<5
15#define HIGH_14 PORTB|=1<<6
16#define HIGH_15 PORTB|=1<<7
17#define HIGH_16 PORTC|=1<<0
18#define HIGH_17 PORTC|=1<<1
19#define HIGH_18 PORTC|=1<<2
20#define HIGH_19 PORTC|=1<<3
21#define HIGH_20 PORTC|=1<<4
22#define HIGH_21 PORTC|=1<<5
23#define HIGH_22 PORTC|=1<<6
24#define HIGH_23 PORTC|=1<<7
25#define HIGH_24 PORTH|=1<<0
26#define HIGH_25 PORTH|=1<<1
27#define HIGH_26 PORTH|=1<<2
28#define HIGH_27 PORTH|=1<<3
29#define HIGH_28 PORTH|=1<<4
30#define HIGH_29 PORTH|=1<<5
31#define HIGH_30 PORTH|=1<<6
32#define HIGH_31 PORTH|=1<<7
33 
34 
35 
36#define LOW_0  PORTD&=~(1<<0)
37#define LOW_1  PORTD&=~(1<<1)
38#define LOW_2  PORTD&=~(1<<2)
39#define LOW_3  PORTD&=~(1<<3)
40#define LOW_4  PORTD&=~(1<<4)
41#define LOW_5  PORTD&=~(1<<5)
42#define LOW_6  PORTD&=~(1<<6)
43#define LOW_7  PORTD&=~(1<<7)
44#define LOW_8  PORTB&=~(1<<0)
45#define LOW_9  PORTB&=~(1<<1)
46#define LOW_10 PORTB&=~(1<<2)
47#define LOW_11 PORTB&=~(1<<3)
48#define LOW_12 PORTB&=~(1<<4)
49#define LOW_13 PORTB&=~(1<<5)
50#define LOW_14 PORTB&=~(1<<6)
51#define LOW_15 PORTB&=~(1<<7)
52#define LOW_16 PORTC&=~(1<<0)
53#define LOW_17 PORTC&=~(1<<1)
54#define LOW_18 PORTC&=~(1<<2)
55#define LOW_19 PORTC&=~(1<<3)
56#define LOW_20 PORTC&=~(1<<4)
57#define LOW_21 PORTC&=~(1<<5)
58#define LOW_22 PORTC&=~(1<<6)
59#define LOW_23 PORTC&=~(1<<7)
60#define LOW_24 PORTH&=~(1<<0)
61#define LOW_25 PORTH&=~(1<<1)
62#define LOW_26 PORTH&=~(1<<2)
63#define LOW_27 PORTH&=~(1<<3)
64#define LOW_28 PORTH&=~(1<<4)
65#define LOW_29 PORTH&=~(1<<5)
66#define LOW_30 PORTH&=~(1<<6)
67#define LOW_31 PORTH&=~(1<<7)

для экперимента, без успешно! ((  Или я не там прописал !??  

maksim
Offline
Зарегистрирован: 12.02.2012

Еще нужно файл PWM.cpp подправить:

Если процессорного времени хватит, то можно и все 54 задействовать, если же нет то нужно разрядность ШИМа понижать.

BabaDusya
BabaDusya аватар
Offline
Зарегистрирован: 13.10.2012

Большое спасибо за быструю реакцию! Попробывал предварительно : сменил в PWM.cpp  начинку на предложенную, дополнив сразу до 54 пинов! и в ...\PWM\PINS не забыл .  И все тоже самое работают в ШИМе только PB4-PB7(10-13),PD0-PD3(18-21)! (  И ещё, если делаю в скетче доп.ю инициализацию в

void setup()

{pinMode(0, OUTPUT);pinMode(1, OUTPUT);........pinMode(54, OUTPUT);

analog.Mode(0, OUTPUT);analog.Mode(1, OUTPUT);..........analog.Mode(54, OUTPUT);}

то начинает работать и PC0-PC4,PD7(33-38)! ( Вроде правильно вычислил..)   А остальные молчат !((  А хотелось бы научиться,надеюсь это возможно, на всех портах(пинах) МЕГИ...  Может что ещё мы не сделали??

maksim
Offline
Зарегистрирован: 12.02.2012

Выводы на выход в этом случае можно настраивать целыми портами:

1DDRA = 0xFF;
2DDRB = 0xFF;
3DDRC = 0xFF;
4DDRF = 0xFF;
5DDRK = 0xFF;

попробуйте снизить частоту:

analog.Frequence(SLOW);

и уменьшить разрядность:

60  pwm++;
61  if(pwm == 100) pwm = 0;
62}

 

BabaDusya
BabaDusya аватар
Offline
Зарегистрирован: 13.10.2012

СПАСИБО Максим!         

HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013

maksim пишет:

И так. Качаем архив, распаковываем его как обычно в ...\arduino-1.х\libraries\ , запускаем IDE, в примерах должна появиться вкладка PWM и в ней 3 примера. 

Перезалейте пожалуйста архив.

HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013

Перезалейте пожалуйста архив, по Вашей сылке битый.

maksim
Offline
Зарегистрирован: 12.02.2012
Сяу Ляу Вей
Offline
Зарегистрирован: 25.10.2013

maksim пишет:
Видеo 

Тоже хочу использовать  составной 2-х монитор, но есть информация  о 4-х или 6-х рамочном  + контроллерном объединителе.

Какая у вас модель?

HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013

Спасибо.

ilyer
Offline
Зарегистрирован: 28.11.2013

а вот частоту следования шим, можно изменить, повысить до 3кгц?

maksim
Offline
Зарегистрирован: 12.02.2012

Нет.

HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013

А какая частота программного ШИМа? На глаз мерцание не заметно, понятно что больше 24 герц.

maksim
Offline
Зарегистрирован: 12.02.2012

Да фиг его знает какая, измерьте. А насчет не видно... я например и 3 кГц вижу - когда взгляд отводишь в сторону видны шлейфы.

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

maksim
Offline
Зарегистрирован: 12.02.2012

Как обещал - новая версия либы. Старую удалить. Как таковая библиотека отсутствует, все находится в файле PWM.ino, который вложен в примеры.

Пример:

01#define PIN_12
02#define PIN_13
03 
04int brightness = 0;    // how bright the LED is
05int fadeAmount = 5;    // how many points to fade the LED by
06 
07void setup() 
08{
09  Init_PWM();
10  analog_Frequence(2); // предделитель от 1 до 7
11}
12 
13void loop() 
14{
15  analog_Write(12, 255-brightness);   
16  analog_Write(13, brightness);
17 
18  brightness = brightness + fadeAmount;
19 
20  if (brightness == 0 || brightness == 255) fadeAmount = -fadeAmount ;
21     
22  delay(50);                           
23}

PWM.ino:

P.S. #define ALL задействует все 20 выводов дуины.

HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013

Спасибо :)

ilyer
Offline
Зарегистрирован: 28.11.2013

то есть выше 490гц нельзя? синусоиду с частотой 400гц на ноги вывести невозможно?

maksim
Offline
Зарегистрирован: 12.02.2012

Почему 490? Как увеличить частоту аппаратного ШИМа читайте тут. Здесвь же программный ШИМ и частота зависит от предделителя и количества задействованых выводов.

ilyer
Offline
Зарегистрирован: 28.11.2013

4 вывода. один с опорнойй синусоидой а 3 - фазные смещенные относ друг друга на 120. как это грамотно описать?

sav13
sav13 аватар
Offline
Зарегистрирован: 17.06.2013

У меня данная библиотека конфликтует IRRemote на UNO (обе используют TIMER2)

Можно ктото задействовал TIMER1 ?

Или проще IRremote перенастроить ?

maksim
Offline
Зарегистрирован: 12.02.2012

Можно сделать как хотите. Как изменить эту любу обсуждалось, а в IRremote есть возможность поменять таймер.

sav13
sav13 аватар
Offline
Зарегистрирован: 17.06.2013

maksim пишет:

Можно сделать как хотите. Как изменить эту любу обсуждалось, а в IRremote есть возможность поменять таймер.

Спасибо. Таймер поменял в IRremote. Все заработало с пол-пинка

ilyer
Offline
Зарегистрирован: 28.11.2013

maksim пишет:

Почему 490? Как увеличить частоту аппаратного ШИМа читайте тут. Здесвь же программный ШИМ и частота зависит от предделителя и количества задействованых выводов.

я о том, можно ли в analogwrite записывать чаще чем 490гц?

суть моей проблемы в том что в analogwrite пишутся значения из массива (256 значений описывающих один период синусоиды). генерируется несущая у которой должна быть частота 400гц на выходе. с частотой шима в 490 я никак не смогу записать 400*256=102400значений в секунду. какие есть варианты?

ites
Offline
Зарегистрирован: 26.12.2013

Не получилось скачать архив. Было интересно посмотреть что там.

amvolkov
Offline
Зарегистрирован: 22.12.2013

Использую эту библиотеку на Arduino Nano. Подключены 1.8 inch TFT color display (HY-1.8 SPI), часы DS1302, датчик температуры и влажности DHT11, энкодер, кнопка и блютуз.  На дисплей вывод время/температура, уровень яркости RGB светодиодов. Светодиоды подключены к аналоговым выходам ( analog.Mode(17, OUTPUT); // R и дальше...) 

Все это работает, но при опросе датчика температуры (раз в минуту) светодиоды мигают.

1float h = dht.readHumidity();
2float t = dht.readTemperature();

Я проверял, именно в этом месте светодиоды тухнут. Где-то было написано, что опрос происходит медленно, 250мс. Без подключения библиотеки PWM.h такого не происходит. А мне нехватает ШИМ выходов. Пробовал разные библиотеки DHT11, заработала только одна.

Подскажите, пожалуйста, как с этим бороться? Менять датчик на DHT22?

sav13
sav13 аватар
Offline
Зарегистрирован: 17.06.2013

amvolkov пишет:

Я проверял, именно в этом месте светодиоды тухнут. Где-то было написано, что опрос происходит медленно, 250мс. Без подключения библиотеки PWM.h такого не происходит. А мне нехватает ШИМ выходов. Пробовал разные библиотеки DHT11, заработала только одна.

Подскажите, пожалуйста, как с этим бороться? Менять датчик на DHT22?

DHT22 быстрее работать не будет, только точнее. Протокол у него тот же. Можно датчик пореже опрашивать. Но программный PWM все равно будет в это время тормозить. Лучше всего поменять датчик на i2C или аналоговый типа LM335. Тогда опрос будет быстрее. 

При стоимости Arduino Pro Micro 3$ может дешевле отдельный контроллер на PWM поставить?

amvolkov
Offline
Зарегистрирован: 22.12.2013

sav13 пишет:

DHT22 быстрее работать не будет, только точнее. Протокол у него тот же. Можно датчик пореже опрашивать. Но программный PWM все равно будет в это время тормозить. Лучше всего поменять датчик на i2C или аналоговый типа LM335. Тогда опрос будет быстрее. 

При стоимости Arduino Pro Micro 3$ может дешевле отдельный контроллер на PWM поставить?

Да, скорее всего, буду пробовать отдельный контроллер...

maksim
Offline
Зарегистрирован: 12.02.2012

amvolkov пишет:

Использую эту библиотеку на Arduino Nano. Подключены 1.8 inch TFT color display (HY-1.8 SPI), часы DS1302, датчик температуры и влажности DHT11, энкодер, кнопка и блютуз.  На дисплей вывод время/температура, уровень яркости RGB светодиодов. Светодиоды подключены к аналоговым выходам ( analog.Mode(17, OUTPUT); // R и дальше...) 

Все это работает, но при опросе датчика температуры (раз в минуту) светодиоды мигают.

1float h = dht.readHumidity();
2float t = dht.readTemperature();

Я проверял, именно в этом месте светодиоды тухнут. Где-то было написано, что опрос происходит медленно, 250мс. Без подключения библиотеки PWM.h такого не происходит. А мне нехватает ШИМ выходов. Пробовал разные библиотеки DHT11, заработала только одна.

Подскажите, пожалуйста, как с этим бороться? Менять датчик на DHT22?

Дело в том, что во время опроса библиотека dht в определенные моменты запрещает прерывания, в результате останавливается и ШИМ. Можно попробовать убрать запреты, закомментировав по всей библиотеке все //cli();, но тогда скорее всего датчик не будет опрашиваться...

amvolkov
Offline
Зарегистрирован: 22.12.2013

Спасибо, maksim! Я понял источник проблемы. Главное, что вся связка у меня работает. Теперь до ума доводить буду. 

kentik
Offline
Зарегистрирован: 28.03.2013

Поделитесь библиотекой плиииз с первого поста. а то файла больше нет.

maksim
Offline
Зарегистрирован: 12.02.2012

Берите эту #30, той уже нет.

NE_XT
NE_XT аватар
Offline
Зарегистрирован: 22.05.2012

maksim пишет:

Берите эту #30, той уже нет.

Кстати на Leonardo не компилируется.

1PWM.ino: In function 'void Init_PWM()':
2PWM:43: error: 'TCCR2A' was not declared in this scope
3PWM:44: error: 'TCCR2B' was not declared in this scope
4PWM:45: error: 'OCR2A' was not declared in this scope
5PWM.ino: In function 'void analog_Frequence(byte)':
6PWM:116: error: 'TCCR2B' was not declared in this scope
7PWM.ino: In function 'void TIMER2_COMPA_vect()':
8PWM:131: error: 'TCNT2' was not declared in this scope
maksim
Offline
Зарегистрирован: 12.02.2012

Потому что у ATmega32U4 отсутствует второй таймер, а единственный 8-ми битный таймер это TIMER0. В теории если замените двойки на нули должно завестись. 

vvadim
Offline
Зарегистрирован: 23.05.2012

Есть готовый пульт на NANO. Свободны только пины 0 и 1. Можно ли на них генерить шим для управления драйвером шагового двигателя? С помощью библиотеки maksima вроде можно, но не будут ли какие то подводные камни.

HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013

Вот так код компилится под мегу 8-ю:

Но ничего не происходит :(