Вопрос про шим на attiny
- Сообщения: 4
- Зарегистрирован: Сб мар 18, 2017 22:31:59
Здравствуйте, делаю шим контроллер на Attiny2313v на 4 канала, с управлением по uart, сейчас для тестов подключил светодиоды с резистором напрямую к выходам мк, в будущем буду подключать через н канальные мосфеты светодиодную ленту, режим шим fastPWM non-inverted, частоты таймеров ставил и 31250 и 125000, но столкнулся с проблемой когда шим выставлен в 0, на выходе постоянно проскакивают короткие импульсы из-за чего подключенный светодиод постоянно еле еле но горит. Такую же картину наблюдал и на тини13, но тогда мне это было не критично и я не стал разбираться изза чего так. Но в данном случае мне это очень критично, из-за этого вопрос почему так происходит и как это побороть софтово или аппаратно?
- Реклама
- Сообщения: 2406
- Зарегистрирован: Ср фев 23, 2011 12:12:31
Такого быть не должно, проблема скорее всего в программе.Ilyasmnv писал(а):на выходе постоянно проскакивают короткие импульсы
и как это побороть софтово или аппаратно?
Для начала надо выложить программу и схему как подключено.
Без этого говорить не о чем.
Глупый не задает вопросы. Глупый и так все знает.
- Сообщения: 4
- Зарегистрирован: Сб мар 18, 2017 22:31:59
Схема простейшая одна нога светодиода на массу другая через 100ом резистор на выход шим, т.к. светодиодов было под рукой только 2 подключил только к OCR0A и OCR0B, светятся оба, ну и провода RX TX и +5 и масса с UART адаптера, такой проблемы нет если порты настроены просто как порт без шима, светодиод когда 0 полностью тухнет.
код пока только такой, им я хотел опробовать как работает UART.
код пока только такой, им я хотел опробовать как работает UART.
Спойлер
Код: Выделить всё
#include <tiny2313.h>
// Declare your global variables here
#define DATA_REGISTER_EMPTY (1<<UDRE)
#define RX_COMPLETE (1<<RXC)
#define FRAMING_ERROR (1<<FE)
#define PARITY_ERROR (1<<UPE)
#define DATA_OVERRUN (1<<DOR)
// USART Receiver buffer
#define RX_BUFFER_SIZE 8
char rx_buffer[RX_BUFFER_SIZE];
#if RX_BUFFER_SIZE <= 256
unsigned char rx_wr_index=0,rx_rd_index=0;
#else
unsigned int rx_wr_index=0,rx_rd_index=0;
#endif
#if RX_BUFFER_SIZE < 256
unsigned char rx_counter=0;
#else
unsigned int rx_counter=0;
#endif
// This flag is set on USART Receiver buffer overflow
bit rx_buffer_overflow;
// USART Receiver interrupt service routine
interrupt [USART_RXC] void usart_rx_isr(void)
{
char status,data;
status=UCSRA;
data=UDR;
if ((status & (FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN))==0)
{
rx_buffer[rx_wr_index++]=data;
#if RX_BUFFER_SIZE == 256
// special case for receiver buffer size=256
if (++rx_counter == 0) rx_buffer_overflow=1;
#else
if (rx_wr_index == RX_BUFFER_SIZE) rx_wr_index=0;
if (++rx_counter == RX_BUFFER_SIZE)
{
rx_counter=0;
rx_buffer_overflow=1;
}
#endif
}
}
#ifndef _DEBUG_TERMINAL_IO_
// Get a character from the USART Receiver buffer
#define _ALTERNATE_GETCHAR_
#pragma used+
char getchar(void)
{
char data;
while (rx_counter==0);
data=rx_buffer[rx_rd_index++];
#if RX_BUFFER_SIZE != 256
if (rx_rd_index == RX_BUFFER_SIZE) rx_rd_index=0;
#endif
#asm("cli")
--rx_counter;
#asm("sei")
return data;
}
#pragma used-
#endif
// Standard Input/Output functions
#include <stdio.h>
void main(void)
{
// Declare your local variables here
char n;
// Crystal Oscillator division factor: 1
#pragma optsize-
CLKPR=(1<<CLKPCE);
CLKPR=(0<<CLKPCE) | (0<<CLKPS3) | (0<<CLKPS2) | (0<<CLKPS1) | (0<<CLKPS0);
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif
// Input/Output Ports initialization
// Port A initialization
// Function: Bit2=In Bit1=In Bit0=In
DDRA=(0<<DDA2) | (0<<DDA1) | (0<<DDA0);
// State: Bit2=T Bit1=T Bit0=T
PORTA=(0<<PORTA2) | (0<<PORTA1) | (0<<PORTA0);
// Port B initialization
// Function: Bit7=In Bit6=In Bit5=In Bit4=Out Bit3=Out Bit2=Out Bit1=In Bit0=In
DDRB=(0<<DDB7) | (0<<DDB6) | (0<<DDB5) | (1<<DDB4) | (1<<DDB3) | (1<<DDB2) | (0<<DDB1) | (0<<DDB0);
// State: Bit7=T Bit6=T Bit5=T Bit4=0 Bit3=0 Bit2=0 Bit1=T Bit0=T
PORTB=(0<<PORTB7) | (0<<PORTB6) | (0<<PORTB5) | (0<<PORTB4) | (0<<PORTB3) | (0<<PORTB2) | (0<<PORTB1) | (0<<PORTB0);
// Port D initialization
// Function: Bit6=In Bit5=Out Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In
DDRD=(0<<DDD6) | (1<<DDD5) | (0<<DDD4) | (0<<DDD3) | (0<<DDD2) | (0<<DDD1) | (0<<DDD0);
// State: Bit6=T Bit5=0 Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T
PORTD=(0<<PORTD6) | (0<<PORTD5) | (0<<PORTD4) | (0<<PORTD3) | (0<<PORTD2) | (0<<PORTD1) | (0<<PORTD0);
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 125,000 kHz
// Mode: Fast PWM top=0xFF
// OC0A output: Non-Inverted PWM
// OC0B output: Non-Inverted PWM
// Timer Period: 2,048 ms
// Output Pulse(s):
// OC0A Period: 2,048 ms Width: 0 us
// OC0B Period: 2,048 ms Width: 0 us
TCCR0A=(1<<COM0A1) | (0<<COM0A0) | (1<<COM0B1) | (0<<COM0B0) | (1<<WGM01) | (1<<WGM00);
TCCR0B=(0<<WGM02) | (0<<CS02) | (1<<CS01) | (1<<CS00);
TCNT0=0x00;
OCR0A=0x00;
OCR0B=0x00;
// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 125,000 kHz
// Mode: Fast PWM top=0x00FF
// OC1A output: Non-Inverted PWM
// OC1B output: Non-Inverted PWM
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer Period: 2,048 ms
// Output Pulse(s):
// OC1A Period: 2,048 ms Width: 0 us
// OC1B Period: 2,048 ms Width: 0 us
// Timer1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=(1<<COM1A1) | (0<<COM1A0) | (1<<COM1B1) | (0<<COM1B0) | (0<<WGM11) | (1<<WGM10);
TCCR1B=(0<<ICNC1) | (0<<ICES1) | (0<<WGM13) | (1<<WGM12) | (0<<CS12) | (1<<CS11) | (1<<CS10);
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;
// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=(0<<TOIE1) | (0<<OCIE1A) | (0<<OCIE1B) | (0<<ICIE1) | (0<<OCIE0B) | (0<<TOIE0) | (0<<OCIE0A);
// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
// Interrupt on any change on pins PCINT0-7: Off
GIMSK=(0<<INT1) | (0<<INT0) | (0<<PCIE);
MCUCR=(0<<ISC11) | (0<<ISC10) | (0<<ISC01) | (0<<ISC00);
// USI initialization
// Mode: Disabled
// Clock source: Register & Counter=no clk.
// USI Counter Overflow Interrupt: Off
USICR=(0<<USISIE) | (0<<USIOIE) | (0<<USIWM1) | (0<<USIWM0) | (0<<USICS1) | (0<<USICS0) | (0<<USICLK) | (0<<USITC);
// USART initialization
// Communication Parameters: 8 Data, 1 Stop, No Parity
// USART Receiver: On
// USART Transmitter: On
// USART Mode: Asynchronous
// USART Baud Rate: 9600
UCSRA=(0<<RXC) | (0<<TXC) | (0<<UDRE) | (0<<FE) | (0<<DOR) | (0<<UPE) | (0<<U2X) | (0<<MPCM);
UCSRB=(1<<RXCIE) | (0<<TXCIE) | (0<<UDRIE) | (1<<RXEN) | (1<<TXEN) | (0<<UCSZ2) | (0<<RXB8) | (0<<TXB8);
UCSRC=(0<<UMSEL) | (0<<UPM1) | (0<<UPM0) | (0<<USBS) | (1<<UCSZ1) | (1<<UCSZ0) | (0<<UCPOL);
UBRRH=0x00;
UBRRL=0x33;
// Analog Comparator initialization
// Analog Comparator: Off
// The Analog Comparator's positive input is
// connected to the AIN0 pin
// The Analog Comparator's negative input is
// connected to the AIN1 pin
ACSR=(1<<ACD) | (0<<ACBG) | (0<<ACO) | (0<<ACI) | (0<<ACIE) | (0<<ACIC) | (0<<ACIS1) | (0<<ACIS0);
// Digital input buffer on AIN0: On
// Digital input buffer on AIN1: On
DIDR=(0<<AIN0D) | (0<<AIN1D);
// Global enable interrupts
#asm("sei")
while (1)
{
// Place your code here
n=getchar();
if (n == '1'){
OCR0A = 0xFF;
UDR='1';
};
if (n == '2'){
OCR0B = 0xFF;
UDR='2';
};
if (n == '3'){
OCR1A = 0xFF;
UDR='3';
};
if (n == '4'){
OCR1B = 0xFF;
UDR='4';
};
if (n == '0'){
OCR0A = 0x00;
OCR0B = 0x00;
OCR1A = 0x00;
OCR1B = 0x00;
UDR='0';
};
}
}Так и должно быть. Чтобы не было импульсов при 0% и 100% заполнении надо выключать аппаратный ШИМ и выставлять порт в нужное значение. Но, мне кажется, что у Вас низкая частота ШИМ и если поднять ее, то светодиод не будет видно и без выключения ШИМ.Ilyasmnv писал(а):но столкнулся с проблемой когда шим выставлен в 0, на выходе постоянно проскакивают короткие импульсы из-за чего подключенный светодиод постоянно еле еле но горит.
Не даром вывод называется Output COMPARE. При совпадении значения счётчика и регистра сравнения, на пин выходит "1", при значении счётчика БОЛЬШЕ значения регистра сравнения - соответственно, "0".
Описаная ситуация не является ошибкой.
Чтобы полностью погасить светодиод, нужно отключать канал сравнения при нулевом значении в регистре.
Небольшая таблица истинности для OCRx = 0, TCNT = x, OCRx = y
0xF0 -> 0 (0xF0 > 0)
0xF1 -> 0
...
0xFF -> 0 (0xFF > 0)
0x00 -> 1 (0x00 <= 0) - Условие выполняется.
0x01 -> 0 (0x01 > 0)
Описаная ситуация не является ошибкой.
Чтобы полностью погасить светодиод, нужно отключать канал сравнения при нулевом значении в регистре.
Небольшая таблица истинности для OCRx = 0, TCNT = x, OCRx = y
0xF0 -> 0 (0xF0 > 0)
0xF1 -> 0
...
0xFF -> 0 (0xFF > 0)
0x00 -> 1 (0x00 <= 0) - Условие выполняется.
0x01 -> 0 (0x01 > 0)
У себя так же проверял на ATTiny13, Timer0, тактирование - 9.6МГц, предделитель - 1. В этом случае, частота ШИМа - ~37.5кГц, но если выставить значение "0x00" в OCR0 - всё равно свечение есть.Z_h_e писал(а):Но, мне кажется, что у Вас низкая частота ШИМ и если поднять ее, то светодиод не будет видно и без выключения ШИМ.
- Реклама
- Сообщения: 2406
- Зарегистрирован: Ср фев 23, 2011 12:12:31
А что я делаю не так? Почему у меня при 0 в OCR ничего не светится? И осциллограф кажет прямую...Z_h_e писал(а):Так и должно быть.
Ph.Correct + toggle on compare.
Глупый не задает вопросы. Глупый и так все знает.
Просто внимания не обращали. Импульс узкий, цифровой осцилл может его и не заметить при медленной разверткеAndTer писал(а):А что я делаю не так?
Дело в том, что у вас режим не FastPWM. про ШИМ с корректной фазой не скажу - ни разу не применял в виду отсутствия необходимости, а вот для FastPWM однозначно характерны 2 ситуации:AndTer писал(а):А что я делаю не так?
1. при OCR=0 будут иголки "вверх", если установлен режим Clear on compare
2. при OCR=255 будут иголки "вниз", если установлен режим Set on compare
(по поводу иголок я мог перепутать - память-то уже не та: может оно и наоборот в зависимости от режима...)
это описано в документации.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
- Сообщения: 1492
- Зарегистрирован: Ср июн 25, 2008 15:19:44
Код: Выделить всё
void Set_Proc_Motor_Stop (void)
{
clr_bit (P_CH_RIGHT_DDR, P_CH_RIGHT);
clr_bit (P_CH_RIGHT_PORT, P_CH_RIGHT);
clr_bit (P_CH_LEFT_DDR, P_CH_LEFT);
clr_bit (P_CH_LEFT_PORT, P_CH_LEFT);
clr_bit (PWM_RIGHT_DDR, PWM_RIGHT);
clr_bit (PWM_LEFT_DDR, PWM_LEFT);
clr_bit (TCCR1A, TMR_COM_RIGHT);
TMR_OCR_RIGHT = 0;
clr_bit (TCCR1A, TMR_COM_LEFT);
TMR_OCR_LEFT = 0;
all_leds_off ();
direction = DIRECTION_STOP;
direction_last = DIRECTION_STOP;
motor_mode = MOTOR_STOP;
_proc_motor = PROC_MOTOR_IDLE;
}
//-----------------------------------------------------------------------------------------
case PROC_MOTOR_BRAKING: // Торможение.
if (handle_soft_timer (ST_PROC_MOTOR))
{
switch (direction)
{
case DIRECTION_RIGHT:
if (TMR_OCR_RIGHT > 0)
TMR_OCR_RIGHT--;
else
Set_Proc_Motor_Stop ();
break;
Знакомая беда, и у меня было такое, как я выкрутился?: использовал вместо прямого ШИМа обратный и у меня иголки перевернулись т.е. теперь при максимальной яркости иголки есть но их всё равно никто не видит 
- Сообщения: 4
- Зарегистрирован: Сб мар 18, 2017 22:31:59
- Сообщения: 1492
- Зарегистрирован: Ср июн 25, 2008 15:19:44
Вообще-то вам дали другой правильный совет. Если значение ШИМ 0, то отключать ШИМ. Отключить режим ШИМ-а у таймера, чтобы на выход иголки не выдавал, вдобавок, для пущей надежности, переводим пин в Hi Z состояние.Ilyasmnv писал(а):alex_ спасибо большое за совет, так и сделал все отлично
Все бы хорошо, но как быть, если нужно погасить ОДИН светодиод из 4-х?..
«Еще я хотел бы, чтобы наши ученые изобрели какой-то новый источник энергии, чтобы мы на коленях не ползали даже перед нашими братьями, умоляя их и выпрашивая тонну нефти или кубометр газа», — рассказал белорусский президент.
- Сообщения: 1492
- Зарегистрирован: Ср июн 25, 2008 15:19:44
Отключаете нужный канал. Смотрите выше мой пример.
- Сообщения: 2406
- Зарегистрирован: Ср фев 23, 2011 12:12:31
то есть никто не пробовал? - Ph.Correct + toggle on compare.
ну ладно. лепите костыли дальше.
ну ладно. лепите костыли дальше.
Глупый не задает вопросы. Глупый и так все знает.
- Сообщения: 4
- Зарегистрирован: Сб мар 18, 2017 22:31:59
AndTer извиняюсь, да сейчас попробовал настроить как phase correct pwm и все прекрасно работает.
А по поводу каждый раз отключать шим мне не нравиться такая идея, ибо на мой взгляд слишком много гемора добавляется.
А по поводу каждый раз отключать шим мне не нравиться такая идея, ибо на мой взгляд слишком много гемора добавляется.
- Сообщения: 1492
- Зарегистрирован: Ср июн 25, 2008 15:19:44
Никакого гемора. Если 0, выключаем шим, если больше нуля, включаем. Либо миритесь с иголками. Сейчас у вас светодиоды. А если двигатель?
- Сообщения: 2406
- Зарегистрирован: Ср фев 23, 2011 12:12:31
Действительно, ставим phase correct pwm и никаких иголок. Частота ниже обычного шим в 2 раза, но так как шим аппаратный, то некритично, просто предделитель поменьше. И ещё в добавок исключаются ситуации когда светодиод вспыхивает при плавном увеличении/уменьшении. Примерно как при использовании BAM.Demiurg писал(а):Никакого гемора.
Глупый не задает вопросы. Глупый и так все знает.
ссылка про 768 светодиодов на обычной атмеге не работает.
так, все-таки, как подключить много светодиодов с помощью ВАМ?
так, все-таки, как подключить много светодиодов с помощью ВАМ?
Мудрость приходит вместе с импотенцией...
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.



