ATtiny2313 и симистор
Добавлено: Ср ноя 23, 2016 22:38:23
Доброй ночи, уважаемые коты. Такой вопрос. Вышел из строя регулятор оборотов гравировальной машины. После изучения схемы, так как китайцы затерли название контроллера, определил, что это скорее всего ATtiny2313. Решил методом реверс-инжиниринга восстановить этот регулятор. В принципе программа не сложная. Разобрался с работой ЖК индикатора. Индикация и управление кнопками работает. Но проблема. Подключил нагрузку, а симистор не открывается. Есть подозрение, что выбрал неправильный режим работы симистора. Так как рисовал схему по существующей плате. А управление симистором делал отрицательным импульсом.
Вот схема
а вот программа
Подскажите, что неправильно
Вот такой регулятор

ЗЫ: И не понятно, в каком квадранте сейчас работает симистор. И в каком должен работать.
Вот схема
а вот программа
Спойлер
Код: Выделить всё
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <avr/eeprom.h>
#include <avr/sleep.h>
#include "button.h"
#define ZERO_CROSS PD2 //Вход импульсов ZERO-CROSS (INT0)
#define control_triac PD1 //Вывод на управляющий электрод симистора
#define v_change_speed 288 //Шаг регулировки изменения скорости
#define t_pulse_triac 50 //Длительность отпирающего импульса симистора 30 мкс (смотреть по ТУ для конкретного симистора)
#define SP_hi 9600 // максимальная скорость
#define SP_lo 1824 // миниимальная скорость
#define SP_m 4992 // средняя скорость
#define COM1 PD3
#define COM2 PD4
#define SEGA PB0
#define SEGB PB1
#define SEGC PB2
#define SEGD PB3
#define SEGE PB4
#define SEGF PB5
#define SEGG PB6
unsigned char segs_out = 0;
volatile unsigned char state_counter = 4;
volatile unsigned char output_change = 0;
unsigned char LCD_out[2] = {0, 0};
unsigned char count;
const unsigned char segment_table[] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F};
unsigned long speed_lcd;
volatile unsigned int speed;
//************************ Функция инициализации ***********************
void initialization(void)
{
DDRB = 0x7F; //7 выходов сегмента
DDRD |= _BV(control_triac); //выход управляющего электрода
PORTD |= _BV(control_triac); //высокий уровень на управляющем выводе
DDRD &= ~_BV(ZERO_CROSS); //вход детектора нуля
PORTD |= _BV(ZERO_CROSS); //с подтягивающим резистором для питания транзистора оптрона
MCUCR |= _BV(ISC00); //внешнее прерывание 0 по любому изменению уровня
// GIMSK |= _BV(INT0); //разрешаем внешнее прерывание 0
// Инициализация Timer/Counter 0
TCCR0B |= (0 << CS02) | (1 << CS01) | (1 << CS00); // = 8МГц/64
TCNT0 = 0xC1;
TIMSK |= _BV(TOIE0)| _BV(OCIE1A); //разрешаем прерывание таймера 0 и таймера 1
}
// Следующая таблица имеет 10 записей для отображения символов 0-9, HEX-значения COM1-COM4
// для входов LCD A & B.
void LCD_print(char digit, unsigned char data)
{
if (digit == 1) LCD_out[0] = segment_table[data / 10];
if (digit == 2) LCD_out[1] = segment_table[data % 10];
}
void LCD_update(void)
{
output_change = 0;
// state_counter генерирует сигналы 2 выходов COM через PORTD,
// каждый имеет состояния HIGH и LOW.
switch (state_counter)
{
case 0:
//вывод десятков:
PORTD &= ~((1 << COM1) | (1 << COM2)); //вывод в режиме Hi-Z
DDRD &= ~((1 << COM1) | (1 << COM2)); //порт D пин 0 работает как ВХОД
segs_out = LCD_out[0];
PORTB = segs_out; //выводим в порт символ
DDRD |= (1 << COM1); //порт D пин 0 работает на ВЫХОД
DDRD &= ~(1 << COM2);
break;
case 1:
PORTD |= (1 << COM1); //
PORTB = segs_out ^ 0xFF;// инверсия выходов сегментов
break;
case 2:
//вывод единиц
PORTD &= ~((1 << COM1) | (1 << COM2)); //вывод в режиме Hi-Z
DDRD &= ~((1 << COM1) | (1 << COM2)); //порт D пин 0 работает как ВХОД
segs_out = LCD_out[1];
PORTB = segs_out;
DDRD |= (1 << COM2); //порт D пин 0 работает на ВЫХОД
DDRD &= ~(1 << COM1);
break;
case 3:
PORTD |= (1 << COM2); //
PORTB = segs_out ^ 0xFF; // инверсия выходов сегментов
break;
default:
DDRB = 0x00;
DDRD &= ~((1 << COM1) | (1 << COM2)); // COM1-COM2 отключены (входы)
}
}
//********************* Обработчик прерывания по переполнению Timer 0 ***************
ISR(TIMER0_OVF_vect)
{
// Перезагрузка значения для Timer 0
// Период Timer0 = 0.125 МГц = 8 МГц / 64.
// 2 мс = 8 мкс * 250
// 5 = 255-250
TCNT0 = 5;
state_counter++;
output_change = 1; // Это флаг для цикла main
if (state_counter > 3)
state_counter = 0;
BtnExe();
}
//********************* Обработчик внешнего прерывания 0 *****************************
ISR (INT0_vect) //По переднему/заднему фронтам импульса ZERO-CROSS
{
OCR1A = 10000 - speed; //Регистру сравнения присваиваем значение скорости
TCCR1B |= _BV(WGM12) | _BV(CS10); //Запускаем таймер 1 в режиме СТС с периодом счёта 1 мкс
}
//********************* Обработчик прерывания по сравнению Timer 1 *******************
ISR (TIMER1_COMPA_vect) //прерывание для формирования открывающего импульса симистора
{
PORTD &= ~_BV(control_triac); //Передний фронт отпирающего импульса симистора
_delay_us (t_pulse_triac); //Длительность отпирающего импульса
PORTD |= _BV(control_triac); //Задний фронт отпирающего импульса симистора
TCCR1B = TCNT1 = 0; //остановка и обнуление таймера 0
}
int main (void)
{
// Вызов функции инициализации (описание см. ниже):
initialization();
BtnInit();
speed = SP_lo; //скорость на середину диапазона
// Разрешить все прерывания:
sei();
while(1)
{
uint8_t button = BtnGet(); //читаем значение кнопок
if (!(BTN_PIN & BTN_POWER)) //если нажата кнопка POWER
{
GIMSK |= _BV(INT0); //разрешаем внешнее прерывание 0
TIMSK |= _BV(OCIE1A); //разрешаем прерывание таймера 1
}
if (BTN_PIN & BTN_POWER) //если отжата кнопка POWER
{
GIMSK &= ~_BV(INT0); //запрещаем внешнее прерывание 0
TCCR1B = TCNT1 = 0;
TIMSK &= ~_BV(OCIE1A); //запрещаем прерывание таймера 1
PORTD |= _BV(control_triac);
}
if (button == BTN_SHRT_UP) //если нажата кнопка +
{
speed += v_change_speed; //увеличиваем скорость с заданным шагом
if(speed > SP_hi) speed = SP_hi;//не выходя за пределы
}
if (button == BTN_SHRT_DOWN) //если нажата кнопка -
{
speed -= v_change_speed; //уменьшаем скорость заданным шагом
if(speed <= SP_lo) speed = SP_lo;//не выходя за пределы
}
speed_lcd = ((unsigned long)speed + 480) * 27 / 7776;
LCD_print(1, speed_lcd);
LCD_print(2, speed_lcd);
if (output_change)
{
LCD_update();
}
}
}
Вот такой регулятор
ЗЫ: И не понятно, в каком квадранте сейчас работает симистор. И в каком должен работать.

