Перейти к содержанию

8ми Канальный Шим На Atmega8


BATCOH

Рекомендуемые сообщения

День добрый.

Нужно управлять свечением 8 светодиодов(U=2,5V, I=15mA) при помощи ШИМ.

В даташите на мегу8 сказано: Three PWM Channels,

что значит 3 канала ШИМ. Но мне нужно 8. Как это можно реализовать?

Программирую на Си в CodeVisionAVR.

Изменено пользователем BATCOH
Ссылка на комментарий
Поделиться на другие сайты

Реклама: ООО ТД Промэлектроника, ИНН: 6659197470, Тел: 8 (800) 1000-321

День добрый.

Нужно управлять свечением 8 светодиодов(U=2,5V, I=15mA) при помощи ШИМ.

В даташите на мегу8 сказано: Three PWM Channels,

что значит 3 канала ШИМ. Но мне нужно 8. Как это можно реализовать?

Программирую на Си в CodeVisionAVR.

Зачем тебе надо эта ШИМ, светодиодами можно управлять и без ШИМ.

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

20% скидка на весь каталог электронных компонентов в ТМ Электроникс!

Акция "Лето ближе - цены ниже", успей сделать выгодные покупки!

Плюс весь апрель действует скидка 10% по промокоду APREL24 + 15% кэшбэк и бесплатная доставка!

Перейти на страницу акции

Реклама: ООО ТМ ЭЛЕКТРОНИКС, ИНН: 7806548420, info@tmelectronics.ru, +7(812)4094849

Выбираем схему BMS для корректной работы литий-железофосфатных (LiFePO4) аккумуляторов

 Обязательным условием долгой и стабильной работы Li-FePO4-аккумуляторов, в том числе и производства EVE Energy, является применение специализированных BMS-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ, также как и для других, очень важен контроль процесса заряда и разряда, а специализированных микросхем для этого вида аккумуляторов не так много. Инженеры КОМПЭЛ подготовили список имеющихся микросхем и возможных решений от разных производителей. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

мне нужно плавно зажигать и гасить 8 светодиодов, одновременно и вразбивку, а также мерцать ими.

Да пожалуйста!

Давай по-порядку. Сначала плавно зажигать и гасить:

- В программе организуются прерывания по таймеру. Относительно высокой частоты.

- Для каждого светодиода заводится индивидуальная однобайтная константа и глобальный однобайтный счетчик.

- В подпрограмме прерываний организуется:

-- Инкрементирование глобального счетчика с проверкой перехода через ноль;

-- В момент перехода через ноль все светодиоды зажигаются.

-- В момент достижения глобальным счетчиком значения константы отдельно взятого светодиода последний гасится;

-- Еще можно предусмотреть наложение глобальной маски по AND на светодиоды, с целью отключения нужных из них совсем.

- В основной программе организуется манипуляция значением констант. Например увеличение и/или уменьшение оных с постоянной/переменной скоростью. Таким образом организуется эффект плавного зажигания и гашения как одновременно, так и по отдельности. Зависит от фантазии.

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

...Мерцать ими...

Ничто не мешеает мерцать ими, так сказать в "ключевом" режиме, при помощи предыдущего способа.

Либо:

- В программе организуются прерывания по таймеру. Относительно высокой частоты.

- Для каждого светодиода заводится индивидуальная однобайтная константа и индивидуальный однобайтный счетчик.

- В подпрограмме прерываний организуется:

-- Проверка на ноль индивидуальных счетчиков, и если это так, то инвертируется состояние соотв. светодиода, а счетчик перезагружается константой;

-- Декремент индивидуальных счетчиков;

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

- В основной программе организуется манипуляция значением констант. Например увеличение и/или уменьшение оных с постоянной/переменной скоростью. Таким образом организуется мерцание с постоянной/переменной частотой. Или загрузка констант из заранее придуманной таблицы. Опять все зависит от фантазии.

Это только два из множества вариантов реализации....

И ты чуствуешь? Как много можно накрутить таким образом, или изменяя предложенный вариант "крутить" что-то своё?

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

Спасибо за советы.

С мерцанием я разберусь)) но с плавным светом с изменением...

У меня сейчас сделано так:

1.включил таймер счетчик Timer/Counter 0

2.задал частоту таймера без предделителя(частота внутренней синхронизации 1МГц)

3.алгоритм шим для 4 каналов:

void pow (unsigned char port0,unsigned char port1,unsigned char port2,unsigned char port3)

{

if ( TCNT0>=port0)PORTD.0 =0;

else PORTD.0 =1;

if ( TCNT0>=port1)PORTD.1 =0;

else PORTD.1 =1;

if ( TCNT0>=port2)PORTD.2 =0;

else PORTD.2 =1;

if ( TCNT0>=port3)PORTD.3 =0;

else PORTD.3 =1;

}

теперь если в main() написать

while(1)

{

pow(40,150,74,0);

}

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

НО!!!!!!!

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

написал функцию для плавного загорания и погасания 4х св.диодов поочерёдно:

void var1(void)

{

while(1)

{

for (a=0;a<=8;a++)

{

if(a==0)//первый светодиод загорается

{

for(i=H;i<=250;i++)

{

delay_ms(TMI);

pow (i,0,0,0);

}

}

if(a==1)//первый светодиод гаснет

{

for(i=250;i>=H;i--)

{

delay_ms(TMI);

pow (i,0,0,0);

}

}

if(a==2)//второй светодиод загорается

{

for(i=H;i<=250;i++)

{

delay_ms(TMI);

pow (0,i,0,0);

}

}

if(a==3) //второй светодиод гаснет

{

for(i=250;i>=H;i--)

{

delay_ms(TMI);

pow (0,i,0,0);

}

}

if(a==4) //третий светодиод загорается

{

for(i=H;i<=250;i++)

{

delay_ms(TMI);

pow (0,0,i,0);

}

}

if(a==5) //третий светодиод гаснет

{

for(i=250;i>=H;i--)

{

delay_ms(TMI);

pow (0,0,i,0);

}

}

if(a==6) //четвертый светодиод загорается

{

for(i=H;i<=250;i++)

{

delay_ms(TMI);

pow (0,0,0,i);

}

}

if(a==7) //четвертый светодиод гаснет

{

for(i=250;i>=H;i--)

{

delay_ms(TMI);

pow (0,0,0,i);

}

}

}

}

}

TMI - время задержки.

При TMI равным 1 или 2 всё работает нормально, но если пытаться увеличить это время, то становиться заметным мерцание св.диодов.

Я думаю что применение задержек delay_ms здесь не уместно.

Да надо думать насчет прерываний...

Изменено пользователем BATCOH
Ссылка на комментарий
Поделиться на другие сайты

Да надо думать насчет прерываний...

Надо.

Вот я бы так сделал (применительно к тому, о чем постил в предудщий раз про плавное управление)

на несуществующем языке - просто для того чтоб не рисовать алгоритм:

однобайтный массив: dV[0..7]	 ;скорость нарастания/уменьшения светимости для каждого светодиода
однобайтный массив: maxV[0..7] ;верхняя граница светимости для каждого светодиода;
однобайтный массив: minV[0..7] ;нижняя граница светимости для каждого светодиода;
однобайтный массив: V[0..7] ;текущее значение светимости для каждого светодиода;

; пример инициализации для светодиода №0
; dV[0]:=01h
; maxV[0]:=F0h
; minV[0]:=10h
; V[0]:=80h

;подпрограмма обслуживания прерываний частотой 5...10Гц
FOR i=0 TO 7
V[i]:=V[i]+dV[i]
IF V[i]>=maxV[i] THEN dV[i]:=-dV[i] : V[i]:=maxV[i]
IF V[i]<=minV[i] THEN dV[i]:=-dV[i] : V[i]:=minV[i]
NEXT i
RETURN
;конец подпрограммы.

Таким образом, скорость, заданная в dV помноженная на герцы подпрограммы, даст реальную скорость нарастания/уменьшения яркости светодиода.

Изменено пользователем Speccy
Ссылка на комментарий
Поделиться на другие сайты

спасибо за псевдокод.

теперь осталось научиться как вызывать программу по прерыванию от переполнения таймера/счетчика для ATmega8 на Си в CodeVisionAVR

Изменено пользователем BATCOH
Ссылка на комментарий
Поделиться на другие сайты

теперь осталось научиться....

Не парь мозги, пиши ассемблером...

Я глянул твой код наверху (быстро перемотал первый раз, и теперь тоже секунды две глядел, и снова перемотал), так ведь черт ногу сломит!

Это наверное потому, что я на СИ вообще не знаю как писать, но всякие простые вещи понять могу. Пугает он меня, как ассемблер тебя видимо.

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

вот набил в Си твой код:

unsigned char dV[8]; //скорость нарастания/уменьшения светимости для каждого светодиода

unsigned char maxV[8];//верхняя граница светимости для каждого светодиода

unsigned char minV[8];//нижняя граница светимости для каждого светодиода

unsigned char V[8];//текущее значение светимости для каждого светодиода

dV[0] = 1;

maxV[0] = 240;

minV[0] = 16;

V[0] = 128;

//программа - обработчик прерываний

interrupt [8] void timer0_overflow(void)

{

for (i=0;i>=7;i++)

{

V=V+dV;

if(V>=maxV)

{

dV=-dV;

V=maxV;

}

if(V<=maxV)

{

dV=-dV;

V=minV;

}

}

}

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

if(V<=maxV)

Я тебе ошибку нашел :)

cпасибо))

но я всё равно не понял твоего алгоритма.

я знаю только этот:

1. циклический таймер/счетчик считает от 0 до 255

2. пишу функцию для ШИМ с аргументом коэфициента заполнения ШИМ:

сравниваем аргумент с текущим значением счетчика, если аргумент больше, то на выходе

ШИМ лог 0, если меньше или равно, то на выходе ШИМ лог 1

3. если эту функцию вызвать в бесконечном цикле и задать аргумент, то получится ШИМ

Изменено пользователем BATCOH
Ссылка на комментарий
Поделиться на другие сайты

я знаю только этот:

1. циклический таймер/счетчик считает от 0 до 255

2. пишу функцию для ШИМ с аргументом коэфициента заполнения ШИМ:

сравниваем аргумент с текущим значением счетчика, если аргумент больше, то на выходе

ШИМ лог 0, если меньше или равно, то на выходе ШИМ лог 1

3. если эту функцию вызвать в бесконечном цикле и задать аргумент, то получится ШИМ

ещё я так и не разобрался с прерыванием по переполнению таймера, компилятор хавает написанную выше функцию, но она не работает((

Я имел в виду, что к этому твоему алгоритму надо довесок в виде того что реализовал в последнем посте на СИ. Но довесок этот должен работать параллельно с алгоритмом. Например ШИМ работает на одном таймере, а довесок на другом таймере. Пока с прерываниями не разберешся ниче не вырастет.

Чтобы понять приведенный мною алгоритм, надо представить себе игру - шарик теннисный, который перемещается только по одной оси. Например Х.

Через каждый момент времени он пролетает расстояние dX. Полет шарика ограничен справа и слева стенками, от которых он отражается и летит в противоположном направлении. Как это описать математически?

Просто через промежутки времени выполнять действие X=X+dX. А вот знак у dX менять при столкновении со стенками. Тогда он будет перемещаться вправо (dx=1) до стенки, и тут знак приращения изменится и он полетит влево (dx=-1) до стенки, а потом опять вправо.

Если ввести еще одну координату, то получится уже двумерное перемещение. С тремя координатами - в объёме.

А если еще dX представить в виде функции F(t)=...., то можно наделать очень интересных эффектов.

В твоем случае у светодиода есть текущее значение светимости для ШИМ (это будет X), и приращение к этой светимости, то есть скорость изменения этой светимости (это будет dX). Чем больше приращение (по модулю), тем быстрее шарик будет скакать туда-сюда (светодиод зажигаться и гаснуть).

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

  • 3 года спустя...

http://www.atmel.com/dyn/resources/prod_do...nts/doc8020.pdf

почитай, там аж 10-канальный ШИМ расписан.

хороший аппноут!!

мне очень понравился алгоритм.

таким образом можно дохрена увеличить количество каналов шим

если организовать мастер-мультислейв систему через 485 интерфейс

1 километр = 1024 метр

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

  • 2 недели спустя...

Можете написать полный код для реализации ШИМ? Можно на 2-3 канала, а то я только недавно начал изучать МК и хотел бы понять ШИМ.

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

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

вот и славно.

в аппноуте все очень хорошо расписано,

надо только читать

если возникнут вопросы, отвечу!

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

1 километр = 1024 метр

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

Написал так: (код не мой, посмотрел выше)

unsigned char a, b;
void pow (unsigned char port0,unsigned char port1,unsigned char port2,unsigned char port3)
{
if ( TCNT1>port0)PORTB.0 =0; 
else PORTB.0 =1;
if ( TCNT1>port1)PORTB.1 =0; 
else PORTB.1 =1;
if ( TCNT1>port2)PORTB.2 =0; 
else PORTB.2 =1; 
if ( TCNT1>port3)PORTB.3 =0; 
else PORTB.3 =1;
}

.

.

.


while (1)
     {
     pow(20, 40, 60, 78);      
     };

В Протеусе работает, проверить в железе пока нет возможности. Какие ещё есть варианты реализации ШИМ?

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

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

Присоединяйтесь к обсуждению

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

Гость
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Ответить в этой теме...

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

  Разрешено использовать не более 75 эмодзи.

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

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

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

Загрузка...
  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
×
×
  • Создать...