Естественно, TIMER1 16-ти битный, в то время как код написан под 8-битный таймер. Будет время сделаю под 16-ти битный. Но можете и сами посмотреть даташит и настоить по аналогии с 8-ми битным.
#define PIN_12
#define PIN_13
int brightness = 0; // how bright the LED is
int fadeAmount = 5; // how many points to fade the LED by
void setup()
{
Init_PWM();
analog_Frequency(2); // предделитель от 1 до 7
}
void loop()
{
analog_Write(12, 255-brightness);
analog_Write(13, brightness);
brightness = brightness + fadeAmount;
if (brightness == 0 || brightness == 255) fadeAmount = -fadeAmount ;
delay(50);
}
P.S. #define ALL задействует все 20 выводов дуины.
Интересная тема. Глубоко "тонет" и всеравно "всплывает" и подход к проблеме очень перспективный.
Я у себя использую совсем небольшую либку для таймера 1. Делает она дето следующее:
1. генерирует временные интервалы от 4мксек до 0,5сек для каждого обслуживаемого "устройства". Величины интервалов задает само устройство на каждом такте.
2. Поддерживает такие "устройства": ШИМ 8 бит на любом пине, сервопривод 8бит на любом пине, ШИМ 8 бит на выводе сдвигового регистра расширения, сервопривод 8бит на выводе сдвигового регистра расширения, произвольное устройство конечный автомат с временными интервалами.
3. Одновременно работающих устройств - 255 (реально пробовал штук 10 - работает). Т.е. часть из них ШИМ, часть сервами ворочает, а какое-то морзянкой мигает.
4. Работа с пинами напрямую, использовать digitalWrite можно, но не желательно.
Работает на Нано и Мини. На других не тестил, должна работать на любом 328.
Если будет письменно подтвержденный массового интереса - могу опубликовать. Просто так не буду, не охота с примерами возится и описание набирать.
Интересная тема. Глубоко "тонет" и всеравно "всплывает" и подход к проблеме очень перспективный.
Я у себя использую совсем небольшую либку для таймера 1. Делает она дето следующее:
1. генерирует временные интервалы от 4мксек до 0,5сек для каждого обслуживаемого "устройства". Величины интервалов задает само устройство на каждом такте.
2. Поддерживает такие "устройства": ШИМ 8 бит на любом пине, сервопривод 8бит на любом пине, ШИМ 8 бит на выводе сдвигового регистра расширения, сервопривод 8бит на выводе сдвигового регистра расширения, произвольное устройство конечный автомат с временными интервалами.
3. Одновременно работающих устройств - 255 (реально пробовал штук 10 - работает). Т.е. часть из них ШИМ, часть сервами ворочает, а какое-то морзянкой мигает.
4. Работа с пинами напрямую, использовать digitalWrite можно, но не желательно.
Работает на Нано и Мини. На других не тестил, должна работать на любом 328.
Если будет письменно подтвержденный массового интереса - могу опубликовать. Просто так не буду, не охота с примерами возится и описание набирать.
А моглибы вы хотябы просто исходниками поделиться ?
Интересует, все-таки, вариант в виде библиотеки (да и ссылки все битые уже). Не могли бы Вы ее выложить сюда. Путем вставки кода в скетчи все получается, но нужен именно библиотечный вариант для вставки в другой мой проект по управлению семисегментным ЖКИ (1/4 multiplex , 1/3 bias)
Сам попытался (после 2 дней разбора семантики Вашего кода), не получается как то создать библиотеку самостоятельно. Знаний и пониманий еще маловато. Подозреваю что можно сделать в таком виде как тут http://robotosha.ru/arduino/multi-tasking-arduino.html
но видать от переизбытка новой информации за единицу времени, мозги переклинивает.А тут еще и работать надо )
Подскажите, кто пользуется этой чудом, почему код программного ШИМ почему-то блокирует обмен по serial. Если в скетче закоментировать строку Init_PWM(); - общение по serial команда/ответ проходят без проблем, как только подключаю код PWM - все, глухо. При попытке вывести значение любой переменной по serial - программа зависает вовсе. Пытался понять, что мешает: предположил, что код PWM задействует ШИМ и на RX TX, так как рассчитан на все пины ардуино. Пробовал оставить только строки с пинами, которые использую - эффект тот же. Видимо там что-то "зарыто" в коде ассемблера...
Попробывал данную опцию на 328 проце. Вроде все работает , но есть одно но. Не понятный мусор на выходах (на любых) , который подсвечивает светодиод. Посмотрел осцилографом , при значении 0 явно виды одиночные импульсы на выходе, также при 255 есть такие же импульсы , только отрицательные. Пробывал поменять проц , вешать доп кондеры на питание, питание приличное , никакого эффекта. Единственно заметил что если analog_Frequence() = 1 или 2 данных помех меньше и подсветка меньше , максимальна при значении 7. Мoжет кто то сталкивался с такой проблемой?
Естественно, TIMER1 16-ти битный, в то время как код написан под 8-битный таймер. Будет время сделаю под 16-ти битный. Но можете и сами посмотреть даташит и настоить по аналогии с 8-ми битным.
http://hwmans.blogspot.com/2014/03/attiny13a.html может кому будет полезно.
Выложите библиотеку пожалуйста.
Создайте в своем проекте новую вкладку с именем PWM:
и копируйте туда это содержимое:
#ifdef ALL #define PIN_0 #define PIN_1 #define PIN_2 #define PIN_3 #define PIN_4 #define PIN_5 #define PIN_6 #define PIN_7 #define PIN_8 #define PIN_9 #define PIN_10 #define PIN_11 #define PIN_12 #define PIN_13 #define PIN_14 #define PIN_15 #define PIN_16 #define PIN_17 #define PIN_18 #define PIN_19 #endif #define SBI(port, pin) asm volatile ("sbi %0, %1" :: "I" (_SFR_IO_ADDR(port)), "I" (pin)) #define CHECK(pwms, port, pin) \ asm volatile ( \ "cpc %0, %1 \n\t" \ "brlo 0f \n\t" \ "cbi %2, %3 \n\t" \ "rjmp 1f \n\t" \ "0: sbi %2, %3 \n\t" \ "1: nop \n\t" \ : "+r" (pwm), "+r" (pwms) \ : "I" (_SFR_IO_ADDR(port)), "I" (pin)\ )\ void Init_PWM() { cli(); TCCR2A = 0; TCCR2B = 3; //CLK OCR2A = 1; TIMSK2 = 2; //разрешаем прерывание по совпадению sei(); #ifdef PIN_0 SBI(DDRD, 0); #endif #ifdef PIN_1 SBI(DDRD, 1); #endif #ifdef PIN_2 SBI(DDRD, 2); #endif #ifdef PIN_3 SBI(DDRD, 3); #endif #ifdef PIN_4 SBI(DDRD, 4); #endif #ifdef PIN_5 SBI(DDRD, 5); #endif #ifdef PIN_6 SBI(DDRD, 6); #endif #ifdef PIN_7 SBI(DDRD, 7); #endif #ifdef PIN_8 SBI(DDRB, 0); #endif #ifdef PIN_9 SBI(DDRB, 1); #endif #ifdef PIN_10 SBI(DDRB, 2); #endif #ifdef PIN_11 SBI(DDRB, 3); #endif #ifdef PIN_12 SBI(DDRB, 4); #endif #ifdef PIN_13 SBI(DDRB, 5); #endif #ifdef PIN_14 SBI(DDRC, 0); #endif #ifdef PIN_15 SBI(DDRC, 1); #endif #ifdef PIN_16 SBI(DDRC, 2); #endif #ifdef PIN_17 SBI(DDRC, 3); #endif #ifdef PIN_18 SBI(DDRC, 4); #endif #ifdef PIN_19 SBI(DDRC, 5); #endif } volatile uint8_t pwm; volatile uint8_t pwms[20]; void analog_Frequency(byte prescaler) { TCCR2B = prescaler; //CLK } void analog_Write(byte pin, byte value) { pwms[pin] = value; } byte analog_State(byte pin) { return pwms[pin]; } ISR(TIMER2_COMPA_vect) { asm volatile ("clr %0" : "+r" (TCNT2)); // TCNT2 = 0; #ifdef PIN_0 CHECK(pwms[0], PORTD, 0); #endif #ifdef PIN_1 CHECK(pwms[1], PORTD, 1); #endif #ifdef PIN_2 CHECK(pwms[2], PORTD, 2); #endif #ifdef PIN_3 CHECK(pwms[3], PORTD, 3); #endif #ifdef PIN_4 CHECK(pwms[4], PORTD, 4); #endif #ifdef PIN_5 CHECK(pwms[5], PORTD, 5); #endif #ifdef PIN_6 CHECK(pwms[6], PORTD, 6); #endif #ifdef PIN_7 CHECK(pwms[7], PORTD, 7); #endif #ifdef PIN_8 CHECK(pwms[8], PORTB, 0); #endif #ifdef PIN_9 CHECK(pwms[9], PORTB, 1); #endif #ifdef PIN_10 CHECK(pwms[10], PORTB, 2); #endif #ifdef PIN_11 CHECK(pwms[11], PORTB, 3); #endif #ifdef PIN_12 CHECK(pwms[12], PORTB, 4); #endif #ifdef PIN_13 CHECK(pwms[13], PORTB, 5); #endif #ifdef PIN_14 CHECK(pwms[14], PORTC, 0); #endif #ifdef PIN_15 CHECK(pwms[15], PORTC, 1); #endif #ifdef PIN_16 CHECK(pwms[16], PORTC, 2); #endif #ifdef PIN_17 CHECK(pwms[17], PORTC, 3); #endif #ifdef PIN_18 CHECK(pwms[18], PORTC, 4); #endif #ifdef PIN_19 CHECK(pwms[19], PORTC, 5); #endif asm volatile ("inc %0" : "+r" (pwm)); //pwm++; }пример кода:
#define PIN_12 #define PIN_13 int brightness = 0; // how bright the LED is int fadeAmount = 5; // how many points to fade the LED by void setup() { Init_PWM(); analog_Frequency(2); // предделитель от 1 до 7 } void loop() { analog_Write(12, 255-brightness); analog_Write(13, brightness); brightness = brightness + fadeAmount; if (brightness == 0 || brightness == 255) fadeAmount = -fadeAmount ; delay(50); }P.S. #define ALL задействует все 20 выводов дуины.
Для ардуино леонардо (китайского образца как про мини выглядит) Нужно менять что ни будь ?
Автор, пожалуйста, сделайте по анадлогии программный ШИМ для ATmega8.
Подскажите на портах где програмный ШИМ только у меня digitalWrite не работает?
Интересная тема. Глубоко "тонет" и всеравно "всплывает" и подход к проблеме очень перспективный.
Я у себя использую совсем небольшую либку для таймера 1. Делает она дето следующее:
1. генерирует временные интервалы от 4мксек до 0,5сек для каждого обслуживаемого "устройства". Величины интервалов задает само устройство на каждом такте.
2. Поддерживает такие "устройства": ШИМ 8 бит на любом пине, сервопривод 8бит на любом пине, ШИМ 8 бит на выводе сдвигового регистра расширения, сервопривод 8бит на выводе сдвигового регистра расширения, произвольное устройство конечный автомат с временными интервалами.
3. Одновременно работающих устройств - 255 (реально пробовал штук 10 - работает). Т.е. часть из них ШИМ, часть сервами ворочает, а какое-то морзянкой мигает.
4. Работа с пинами напрямую, использовать digitalWrite можно, но не желательно.
Работает на Нано и Мини. На других не тестил, должна работать на любом 328.
Если будет письменно подтвержденный массового интереса - могу опубликовать. Просто так не буду, не охота с примерами возится и описание набирать.
Интересная тема. Глубоко "тонет" и всеравно "всплывает" и подход к проблеме очень перспективный.
Я у себя использую совсем небольшую либку для таймера 1. Делает она дето следующее:
1. генерирует временные интервалы от 4мксек до 0,5сек для каждого обслуживаемого "устройства". Величины интервалов задает само устройство на каждом такте.
2. Поддерживает такие "устройства": ШИМ 8 бит на любом пине, сервопривод 8бит на любом пине, ШИМ 8 бит на выводе сдвигового регистра расширения, сервопривод 8бит на выводе сдвигового регистра расширения, произвольное устройство конечный автомат с временными интервалами.
3. Одновременно работающих устройств - 255 (реально пробовал штук 10 - работает). Т.е. часть из них ШИМ, часть сервами ворочает, а какое-то морзянкой мигает.
4. Работа с пинами напрямую, использовать digitalWrite можно, но не желательно.
Работает на Нано и Мини. На других не тестил, должна работать на любом 328.
Если будет письменно подтвержденный массового интереса - могу опубликовать. Просто так не буду, не охота с примерами возится и описание набирать.
А моглибы вы хотябы просто исходниками поделиться ?
А моглибы вы хотябы просто исходниками поделиться ?
Пробуйте.
https://cloud.mail.ru/public/5ZoS/8W79KQrZJhttps://cloud.mail.ru/public/5ZoS/8W79KQrZJ
Слегка обрезаная. Без сдвигового регистра как стандартного устройства. Его сейчас потестить не на чем.
Простенький пример.
#include "Timer1.h" #define LED_PIN 13 #define SHIM_PIN 12 #define SERVO_PIN A1 byte StatusSOS; word SOS(void* c) { byte status=*(byte*)c; word pause=20000; switch (status) { case 0: return pause; case 1: case 3: case 5: case 13: case 15: case 17: Set1: SetPin(LED_PIN, HIGH); goto NextStatus; case 7: case 9: case 11: pause*=3; goto Set1; case 25: status=0; default: SetPin(LED_PIN, LOW); NextStatus: *(byte*)c=status+1; return pause; } } TIMER1_ADD_PWM(Shim1, SHIM_PIN) TIMER1_ADD_SERVO(Servo1,SERVO_PIN) TIMER1_INTERRUPT_LIST_BEGIN TIMER1_INTERRUPT_LIST_ADD(SOS, &StatusSOS) TIMER1_INTERRUPT_LIST_SERVO_ADD(Servo1) TIMER1_INTERRUPT_LIST_PWM_ADD(Shim1) TIMER1_INTERRUPT_LIST_END TIMER1 Timer1SystemObject; void setup() { pinMode(SHIM_PIN, OUTPUT); pinMode(SERVO_PIN, OUTPUT); pinMode(LED_PIN, OUTPUT); Serial.begin(115200); Servo1.Status=1; Shim1.Status=1; StatusSOS=1; } void loop() { delay(100); Servo1.Phase+=1; Shim1.Phase+=10; }Шевелит сервой, шимует светодиод а вторым светодиодом SOS сигналит.
А моглибы вы хотябы просто исходниками поделиться ?
Пробуйте.
https://cloud.mail.ru/public/5ZoS/8W79KQrZJhttps://cloud.mail.ru/public/5ZoS/8W79KQrZJ
Слегка обрезаная. Без сдвигового регистра как стандартного устройства. Его сейчас потестить не на чем.
Ссылка не работатет, не могу скачать
Наверно потому что задвоилась при вставке https://cloud.mail.ru/public/5ZoS/8W79KQrZJ
У меня на уно вообще никак не работает, хотя компилируется без ошибок
Подскажите, что не так.
Делаю DMX диммер на програмном шиме, нет определяется уровень, где копать, вот так работаек как свитч
#include <DMXSerial.h> #define PIN_13 void setup() { DMXSerial.init(DMXReceiver); } void loop() { unsigned long lastPacket = DMXSerial.noDataSince(); analogWrite(13, DMXSerial.read(1)); }ав от так ваще ничего
#include <DMXSerial.h> #define PIN_13 void setup() { DMXSerial.init(DMXReceiver); Init_PWM(); analog_Frequence(2); } void loop() { unsigned long lastPacket = DMXSerial.noDataSince(); analog_Write(13, DMXSerial.read(1)); }Здравствуйте, Максим!
Интересует, все-таки, вариант в виде библиотеки (да и ссылки все битые уже). Не могли бы Вы ее выложить сюда. Путем вставки кода в скетчи все получается, но нужен именно библиотечный вариант для вставки в другой мой проект по управлению семисегментным ЖКИ (1/4 multiplex , 1/3 bias)
Сам попытался (после 2 дней разбора семантики Вашего кода), не получается как то создать библиотеку самостоятельно. Знаний и пониманий еще маловато. Подозреваю что можно сделать в таком виде как тут http://robotosha.ru/arduino/multi-tasking-arduino.html
но видать от переизбытка новой информации за единицу времени, мозги переклинивает.А тут еще и работать надо )
Заранее, премного благодарствую!!
Подскажите, кто пользуется этой чудом, почему код программного ШИМ почему-то блокирует обмен по serial. Если в скетче закоментировать строку Init_PWM(); - общение по serial команда/ответ проходят без проблем, как только подключаю код PWM - все, глухо. При попытке вывести значение любой переменной по serial - программа зависает вовсе. Пытался понять, что мешает: предположил, что код PWM задействует ШИМ и на RX TX, так как рассчитан на все пины ардуино. Пробовал оставить только строки с пинами, которые использую - эффект тот же. Видимо там что-то "зарыто" в коде ассемблера...
Моя программа:
#define PIN_4 #define PIN_7 int brightnessDDR = 0; // яркость модулей ОЗУ int fadeAmountDDR = 1; // прирощение яркости ОЗУ int modDDR = 3; // режим подсветки ОЗУ int incomingByte; // переменная сериал void setup() { Init_PWM(); analog_Frequence(3); // предделитель от 1 до 7 частоты ШИМ pinMode(4, OUTPUT); pinMode(7, OUTPUT); Serial.begin(9600); // скорость порта 9600 } void loop() { if (Serial.available() > 0) { incomingByte = Serial.read() ; if(incomingByte == '0'){ modDDR = 0 ; Serial.println("Подсветка DDR отключена") ; } else if (incomingByte == '1'){ modDDR = 1 ; Serial.println("Подсветка DDR постоянное свечение") ; } else if (incomingByte == '2'){ modDDR = 2 ; Serial.println("Подсветка DDR синхронное дыхание") ; } else if (incomingByte == '3'){ modDDR = 3 ; Serial.println("Подсветка DDR асинхронное дыхание") ; } } if (modDDR == 0) { brightnessDDR = 0 ; analog_Write(4, brightnessDDR) ; analog_Write(7, brightnessDDR) ; } if (modDDR == 1) { brightnessDDR = 50 ; analog_Write(4, brightnessDDR) ; analog_Write(7, brightnessDDR) ; } if (modDDR == 2) { analog_Write(4, brightnessDDR) ; analog_Write(7, brightnessDDR) ; brightnessDDR = brightnessDDR + fadeAmountDDR ; if (brightnessDDR == 0 || brightnessDDR == 50) { fadeAmountDDR = -fadeAmountDDR ; } } if (modDDR == 3) { analog_Write(4, 50-brightnessDDR) ; analog_Write(7, brightnessDDR) ; brightnessDDR = brightnessDDR + fadeAmountDDR ; if (brightnessDDR == 0 || brightnessDDR == 50) { fadeAmountDDR = -fadeAmountDDR ; } } delay(40); }#ifdef ALL #define PIN_0 #define PIN_1 #define PIN_2 #define PIN_3 #define PIN_4 #define PIN_5 #define PIN_6 #define PIN_7 #define PIN_8 #define PIN_9 #define PIN_10 #define PIN_11 #define PIN_12 #define PIN_13 #define PIN_14 #define PIN_15 #define PIN_16 #define PIN_17 #define PIN_18 #define PIN_19 #endif #define SBI(port, pin) asm volatile ("sbi %0, %1" :: "I" (_SFR_IO_ADDR(port)), "I" (pin)) #define CHECK(pwms, port, pin) \ asm volatile ( \ "cp %0, %1 \n\t" \ "brlo 0f \n\t" \ "cbi %2, %3 \n\t" \ "rjmp 1f \n\t" \ "0: sbi %2, %3 \n\t" \ "1: nop \n\t" \ : "+r" (pwm), "+r" (pwms) \ : "I" (_SFR_IO_ADDR(port)), "I" (pin)\ )\ void Init_PWM() { cli(); TCCR2A = 0; TCCR2B = 3; //CLK OCR2A = 1; TIMSK2 = 2; //разрешаем прерывание по совпадению sei(); #ifdef PIN_0 SBI(DDRD, 0); #endif #ifdef PIN_1 SBI(DDRD, 1); #endif #ifdef PIN_2 SBI(DDRD, 2); #endif #ifdef PIN_3 SBI(DDRD, 3); #endif #ifdef PIN_4 SBI(DDRD, 4); #endif #ifdef PIN_5 SBI(DDRD, 5); #endif #ifdef PIN_6 SBI(DDRD, 6); #endif #ifdef PIN_7 SBI(DDRD, 7); #endif #ifdef PIN_8 SBI(DDRB, 0); #endif #ifdef PIN_9 SBI(DDRB, 1); #endif #ifdef PIN_10 SBI(DDRB, 2); #endif #ifdef PIN_11 SBI(DDRB, 3); #endif #ifdef PIN_12 SBI(DDRB, 4); #endif #ifdef PIN_13 SBI(DDRB, 5); #endif #ifdef PIN_14 SBI(DDRC, 0); #endif #ifdef PIN_15 SBI(DDRC, 1); #endif #ifdef PIN_16 SBI(DDRC, 2); #endif #ifdef PIN_17 SBI(DDRC, 3); #endif #ifdef PIN_18 SBI(DDRC, 4); #endif #ifdef PIN_19 SBI(DDRC, 5); #endif } volatile uint8_t pwm; volatile uint8_t pwms[20]; void analog_Frequence(byte prescaler) { TCCR2B = prescaler; //CLK } void analog_Write(byte pin, byte value) { pwms[pin] = value; } byte analog_State(byte pin) { return pwms[pin]; } ISR(TIMER2_COMPA_vect) { TCNT2 = 0; // asm volatile ("clr %0" : "+r" (TCNT2)); #ifdef PIN_0 CHECK(pwms[0], PORTD, 0); #endif #ifdef PIN_1 CHECK(pwms[1], PORTD, 1); #endif #ifdef PIN_2 CHECK(pwms[2], PORTD, 2); #endif #ifdef PIN_3 CHECK(pwms[3], PORTD, 3); #endif #ifdef PIN_4 CHECK(pwms[4], PORTD, 4); #endif #ifdef PIN_5 CHECK(pwms[5], PORTD, 5); #endif #ifdef PIN_6 CHECK(pwms[6], PORTD, 6); #endif #ifdef PIN_7 CHECK(pwms[7], PORTD, 7); #endif #ifdef PIN_8 CHECK(pwms[8], PORTB, 0); #endif #ifdef PIN_9 CHECK(pwms[9], PORTB, 1); #endif #ifdef PIN_10 CHECK(pwms[10], PORTB, 2); #endif #ifdef PIN_11 CHECK(pwms[11], PORTB, 3); #endif #ifdef PIN_12 CHECK(pwms[12], PORTB, 4); #endif #ifdef PIN_13 CHECK(pwms[13], PORTB, 5); #endif #ifdef PIN_14 CHECK(pwms[14], PORTC, 0); #endif #ifdef PIN_15 CHECK(pwms[15], PORTC, 1); #endif #ifdef PIN_16 CHECK(pwms[16], PORTC, 2); #endif #ifdef PIN_17 CHECK(pwms[17], PORTC, 3); #endif #ifdef PIN_18 CHECK(pwms[18], PORTC, 4); #endif #ifdef PIN_19 CHECK(pwms[19], PORTC, 5); #endif asm volatile ("inc %0" : "+r" (pwm)); //pwm++; }Так где можно найти библиотеку от Maksima?
Попробывал данную опцию на 328 проце. Вроде все работает , но есть одно но. Не понятный мусор на выходах (на любых) , который подсвечивает светодиод. Посмотрел осцилографом , при значении 0 явно виды одиночные импульсы на выходе, также при 255 есть такие же импульсы , только отрицательные. Пробывал поменять проц , вешать доп кондеры на питание, питание приличное , никакого эффекта. Единственно заметил что если
analog_Frequence() = 1 или 2 данных помех меньше и подсветка меньше , максимальна при значении 7. Мoжет кто то сталкивался с такой проблемой?