Контроллер света на Attiny13

Обсуждаем контроллеры компании Atmel.
Ответить
Мучитель микросхем
Аватара пользователя
Сообщения: 414
Зарегистрирован: Ср янв 26, 2011 13:43:30
Откуда: С того берега моря

Сообщение Jman »

Всем привет. Собираю проект для контроля света в гараже. Суть такая, прикошатил ПИР датчик с дискретным выходом, фотодатчик с оу с выходом 0-5В и клавишу включения 220В, так же есть регулировка чувствительности фотосенсора потенциометром. Алгоритм придумал такой: Если темно и человек заходит в зону ПИР датчика, включаю через задержку лампу, ухожу - из поле ПИРА, через задержку выключаю (ПИР сам формирует задержку от ложных срабатываний). Если светло, лампу не включаю, если нажимаю клавишу включения света - то включаю лампу в любом случае (главный приоритет), если забыли выключить клавишу, через несколько часов отключаем свет (в коде я пока много не ставил, что бы в проверить можно было). В программирование не особо силен (особенно в настройке периферии). Нужна помощь. Начал кодить, и что-то проект мой что в железе, что в протеусе сходит с ума. Проект делал в CVAVR. Исходник с файлом протеуса в пристежке. Ткните, что я не так сделал.
ЗЫ: Использую настройки тактирования камня по дефалту. т.е 9,6МГц/CKDIV = 1,2МГц... Таймер тикает на 1,200000/8 = 150 000.

Схема: Изображение
Вложения
Project.rar
(57.94 КБ) 149 скачиваний
[color=#4080FF]- Бежит этот подлец-электрон, а вокруг его масса (аж 10 в 23й) штук ионов кремния и 10 в 15й ионов примеси и он, подлец, взаимодействует![/color]
Контактная информация:
Реклама
Идёт направо - песнь заводит, Налево - сказку говорит.
Аватара пользователя
Сообщения: 5000
Зарегистрирован: Чт апр 21, 2011 17:55:50
Откуда: Иркутск

Сообщение СКАЗОЧНИК »

А как 8 битным таймером считать несколько часов??? :shock: :dont_know:

Еще, лень распаковывать проект, тем более, у меня нет КодеВижена, зато есть АВРСтудия, в которую по любому ваш код не смогу портировать... Поэтому, если не сложно, то выложите свой код в теги под спойлер.
Станислав
Реклама
Мучитель микросхем
Аватара пользователя
Сообщения: 414
Зарегистрирован: Ср янв 26, 2011 13:43:30
Откуда: С того берега моря

Сообщение Jman »

СКАЗОЧНИК писал(а):А как 8 битным таймером считать несколько часов??? :shock: :dont_know:

Еще, лень распаковывать проект, тем более, у меня нет КодеВижена, зато есть АВРСтудия, в которую по любому ваш код не смогу портировать... Поэтому, если не сложно, то выложите свой код в теги под спойлер.
Вроде все настроил, в протеусе пашет... Только проверил. Настроил таймер по переполнению CTC Mode, в OCRA записал 95 - это дало мне 1 мс. По поводу пари часов, разве не получится инкрементируя переменную накопить нужное число и выполнить действие?
Вот инит:

Код: Выделить всё

// 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 B initialization
// Function: Bit5=In Bit4=In Bit3=Out Bit2=In Bit1=In Bit0=In 
DDRB=(0<<DDB5) | (0<<DDB4) | (1<<DDB3) | (0<<DDB2) | (0<<DDB1) | (0<<DDB0);
// State: Bit5=T Bit4=P Bit3=1 Bit2=T Bit1=P Bit0=T 
PORTB=(0<<PORTB5) | (1<<PORTB4) | (1<<PORTB3) | (0<<PORTB2) | (1<<PORTB1) | (0<<PORTB0);

// ADC initialization
// ADC Clock frequency: 150,000 kHz
// ADC Bandgap Voltage Reference: Off
// ADC Auto Trigger Source: Free Running
// Digital input buffers on ADC0: On, ADC1: On, ADC2: On, ADC3: On
DIDR0=(0<<ADC0D) | (0<<ADC2D) | (0<<ADC3D) | (0<<ADC1D);
ADMUX=FIRST_ADC_INPUT | ADC_VREF_TYPE;
ADCSRA=(1<<ADEN) | (1<<ADSC) | (1<<ADATE) | (0<<ADIF) | (1<<ADIE) | (1<<ADPS2) | (1<<ADPS1) | (0<<ADPS0);
ADCSRB=(0<<ADTS2) | (0<<ADTS1) | (0<<ADTS0);

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 150,000 kHz
// Mode: CTC top=OCR0A
// Timer Period: 1 ms
TCCR0A=(0<<COM0A1) | (0<<COM0A0) | (0<<COM0B1) | (0<<COM0B0) | (1<<WGM01) | (0<<WGM00);
TCCR0B=(0<<WGM02) | (0<<CS02) | (1<<CS01) | (1<<CS00);
TCNT0=0x00;
OCR0A=0x95;
OCR0B=0x00;

// Timer/Counter 0 Interrupt(s) initialization
TIMSK0=(0<<OCIE0B) | (1<<OCIE0A) | (0<<TOIE0);

#asm("sei")
Вот мєйн:

Код: Выделить всё

//RC intrrnal Clock 9,6Mhz 
#include <tiny13.h>
#include <delay.h>
#define out PORTB.3 // Лампа;
#define pir PINB.0  // PIR-датчик;
#define key PINB.1  // Выключатель;
#define debounce 10000
#define pir_delay 30
#define lamp_off_time 60000
#define off_time 50
#define FIRST_ADC_INPUT 1
#define LAST_ADC_INPUT 2
unsigned int adc_data[LAST_ADC_INPUT-FIRST_ADC_INPUT+1];
// Bandgap Voltage Reference: Off
#define ADC_VREF_TYPE ((0<<REFS0) | (0<<ADLAR))

// ADC interrupt service routine
// with auto input scanning
interrupt [ADC_INT] void adc_isr(void)
{
static unsigned char input_index=0;
// Read the AD conversion result
adc_data[input_index]=ADCW;
// Select next ADC input
if (++input_index > (LAST_ADC_INPUT-FIRST_ADC_INPUT))
   input_index=0;
ADMUX=(FIRST_ADC_INPUT | ADC_VREF_TYPE)+input_index;
// Delay needed for the stabilization of the ADC input voltage
delay_us(10);
// Start the AD conversion
ADCSRA|=(1<<ADSC);
}

volatile unsigned int on=0, tic_tac=0, tic_down=0;              // Счетчик;
volatile unsigned int outdoor_sensor;               // Датчик света;
volatile unsigned int sensivity;                    // Регулировка чувствительности;
volatile unsigned char key_on_flag = 0;             // состояние выключателя 0 - выключен; 

// Timer 0 output compare A interrupt service routine
interrupt [TIM0_COMPA] void timer0_compa_isr(void)
{
   static unsigned char counter = 15;               // Счетчик для сетевого віключателя;

   TCNT0=0x00;
   if(key)
    {
        // считали 1 - похоже, выключен;
        // проверяем сколько времени прошло;
        if(counter)
            {
                // время не вышло;
                counter --;
            }
        else
            {
                // прошло 15 миллисекунд выключатель выключен
                key_on_flag = 0;
                counter = 15; // устанавливаем счётчик заново
            }
    }
    else
    {
        // считали 0 - включён
        key_on_flag = 1;
        counter = 20; // устанавливаем счётчик заново
    } 
   if (key_on_flag)                // Запуск таймера включения кнопки (антидребезг);
        tic_tac++;
            else tic_tac=0; 
    
    if (!pir && key_on_flag==0){    // Задержка на включение, антидребезг ПИР дачика;
     on++;
     }
      else   
      {
        on=0;
        //TCNT0=0;
      } 
            
   
}

void adc_read (void)         // Функция считывания значения из АЦП. АЦП 8бит;
{
 outdoor_sensor=adc_data[1]; // Значение 1 канала, PORTB2 ;
 sensivity=adc_data[0];      // Значение 2 канала читаем из массива сканированных каналов АЦП, PORTB4;
}

void main(void)
{

unsigned char key_on = 0; // состояние выключателя
#include <init_PIR.c>
//  Обнуляю порты;
out=0;

// Global enable interrupts


for(;;)
      {  
      // считываем состояние выключателя;
      #asm("cli")           // Запрещаем глобальные прерывания;
      key_on = key_on_flag;
      #asm("sei")           // Разрешаем глобальніе прерівания;
           
        if (key_on==1 && tic_tac>=debounce) // Приоритет включения по клавише;     
        {
            out=1;                       
            while (key_on==1 && tic_tac>=lamp_off_time) 
            {
                out=0; 
            } 
            
            
        }
         else 
         {
           adc_read ();                                      //Функция чтения значения из АЦП (0-255);
       
           if (!pir&&on>=pir_delay&&outdoor_sensor>=sensivity)  // Пир сработал, выключатель отключен, фотодатчик сработал;
            
            out = 1;                      // Порт включен;          
               // else if (pir||((outdoor_sensor<=sensivity)||outdoor_sensor==0)&&  tic_down>=off_time)  
                 //   out = 0;             
                else 
                    out = 0;              // Порт выключен;
         }           
             
    }   
}
Я потом это перенесу в Атмел студио. Кодвижн использую только для настройки... Пока не совсем могу хорошо настроить периферию...
[color=#4080FF]- Бежит этот подлец-электрон, а вокруг его масса (аж 10 в 23й) штук ионов кремния и 10 в 15й ионов примеси и он, подлец, взаимодействует![/color]
Контактная информация:
Идёт направо - песнь заводит, Налево - сказку говорит.
Аватара пользователя
Сообщения: 5000
Зарегистрирован: Чт апр 21, 2011 17:55:50
Откуда: Иркутск

Сообщение СКАЗОЧНИК »

А почему таймер не делится на 1024? можно же еще медленнее сделать...

Код: Выделить всё

	clr temp
			out TCCR0A, temp				; Нормальный режим счета (выводы отключены)
			out TCNT0, temp						; Очищаем счетный регистр

			ldi temp, (0<<FOC0A)|(0<<FOC0B)|(0<<WGM02)|(1<<CS02)|(0<<CS01)|(1<<CS00) ; Делитель 1024
			out TCCR0B, temp

			ldi temp, (0<<OCIE0B)|(0<<OCIE0A)|(1<<TOIE0)	; Разрешаем прерывание по переполнению
			out TIMSK0, temp
С Си языком я плохо дружу. ))) Но зато сейчас много кто поможет. Особенно, если тему перенесут в микроконтроллеры АВР.

А АЦП я как- то так запускал. Может поможет чем...

Код: Выделить всё

	ldi temp, (0<<REFS0)|(1<<ADLAR)|(1<<MUX1)|(0<<MUX0)				; АЦП: опорное 5 В питания; сдвиг влево результата; вывод для считывания РВ4
			out ADMUX, temp

			ldi temp, (1<<ADEN)|(1<<ADSC)|(1<<ADATE)|(1<<ADIE)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0)
			out ADCSRA, temp												; АЦП: запуск; постоянные преобразования; прерывания; прескалер/128

			ldi temp, (0<<ADTS2)|(0<<ADTS1)|(0<<ADTS0)						; АЦП: свободный запуск/ непрерывный режим
			out ADCSRB, temp
Станислав
Реклама
Эиком - электронные компоненты и радиодетали
Друг Кота
Аватара пользователя
Сообщения: 3459
Зарегистрирован: Ср сен 27, 2006 16:18:57

Сообщение Барсик »

В проекте, который Вы выложили в начале этой темы, инициализация периферии сделана правильно, кроме одного.
Выкиньте этот кусок кода нафиг. Совсем. Тогда тактовая частота будет определяться только фьюзами CKSEL0, CKSEL1 и CKDIV8.
А если он Вам очень дорог, то сделайте предделитель на 8:

Код: Выделить всё

// Crystal Oscillator division factor: 8
#pragma optsize-
CLKPR=(1<<CLKPCE);
CLKPR=(0<<CLKPCE) | (0<<CLKPS3) | (0<<CLKPS2) | (1<<CLKPS1) | (1<<CLKPS0);
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif


Вот тогда и получится тактовая 1,2 МГц.
Jman писал(а):

Код: Выделить всё

// ADC Auto Trigger Source: Free Running
Опять взялись за старое? Сделайте как файле проекта

Код: Выделить всё

// ADC Auto Trigger Source: Timer0 Compare Match A
Реклама
Мучитель микросхем
Аватара пользователя
Сообщения: 414
Зарегистрирован: Ср янв 26, 2011 13:43:30
Откуда: С того берега моря

Сообщение Jman »

Я читал давно где-то на форуме, что free running не очень хорошая идея. А вот почему, можете объяснить? PS: осциллограф не поверите, вчера пришел ко мне...
[color=#4080FF]- Бежит этот подлец-электрон, а вокруг его масса (аж 10 в 23й) штук ионов кремния и 10 в 15й ионов примеси и он, подлец, взаимодействует![/color]
Контактная информация:
Реклама
Друг Кота
Аватара пользователя
Сообщения: 3459
Зарегистрирован: Ср сен 27, 2006 16:18:57

Сообщение Барсик »

Jman писал(а):free running не очень хорошая идея
Почему? Очень даже нормальный режим, когда надо делать очень много отсчётов за короткое время. АЦП перезапускает сам себя. Остаётся только считывать результат по прерыванию. Короче цикла не придумаешь.
А для Вашей задачи, одного отсчёта каждую миллисекунду более чем достаточно, поэтому режим Free Running нафиг не нужен.

В начале обработчика прерывания от таймера выведите в порт единичку, а в конце обработчика - нолик. И посмотрите осциллографом, как оно работает. А то протеус конечно хорошо, но в живую лучше.

Кстати, чуть не забыл. При работе таймера в режиме CTC, в регистр сравнения OCR0A надо записывать число на единицу меньше, чем получилось по расчёту. Т.е. чтобы получилась ровно миллисекунда, надо прописать 149, а не 150.
Мучитель микросхем
Аватара пользователя
Сообщения: 414
Зарегистрирован: Ср янв 26, 2011 13:43:30
Откуда: С того берега моря

Сообщение Jman »

Так, все заработало. Я тут немного подправил. Осталось логику додумать, ибо фотодатчик получился слишком не инерционен..
[color=#4080FF]- Бежит этот подлец-электрон, а вокруг его масса (аж 10 в 23й) штук ионов кремния и 10 в 15й ионов примеси и он, подлец, взаимодействует![/color]
Контактная информация:
Мучитель микросхем
Аватара пользователя
Сообщения: 414
Зарегистрирован: Ср янв 26, 2011 13:43:30
Откуда: С того берега моря

Сообщение Jman »

Всем привет... Есть вопрос. Я никак не могу сделать отключение выхода, если у меня пройдет пару часов. Таймер тикает раз в 1 мс. Я делаю так:

Код: Выделить всё


volatile unsigned long int overflow_time = 3600000; // 1 час... 

 if (key_on_flag==1)                // Запуск таймера включения кнопки (антидребезг);
         {
             tic_tac++;
             if (i==0 || i<overflow_time) {i++;}
         }
               else { tic_tac=0; i=0; }
// main

Код: Выделить всё

  if (key_on==1 && tic_tac>=debounce) // Приоритет включения по клавише;
        {
            out=1;

           while (key_on==1 && i>=overflow_time)//lamp_off_time)
            {
                out=0;
            }

           if (key_on==0)
            {
                out=0;
            }
        }

Блин не работает... Если пишу например

Код: Выделить всё

volatile unsigned long int overflow_time = 60000; 
Все работает хорошо... В чем затык?
[color=#4080FF]- Бежит этот подлец-электрон, а вокруг его масса (аж 10 в 23й) штук ионов кремния и 10 в 15й ионов примеси и он, подлец, взаимодействует![/color]
Контактная информация:
Друг Кота
Аватара пользователя
Сообщения: 3459
Зарегистрирован: Ср сен 27, 2006 16:18:57

Сообщение Барсик »

А переменная i у Вас тоже типа unsigned long int ?
Мучитель микросхем
Аватара пользователя
Сообщения: 414
Зарегистрирован: Ср янв 26, 2011 13:43:30
Откуда: С того берега моря

Сообщение Jman »

Барсик писал(а):А переменная i у Вас тоже типа unsigned long int ?
ой нет... Видимо до 65535 считает...

Код: Выделить всё

volatile unsigned int i=0
Сейчас сделал так, не знаю правильно или нет... Сижу жду когда час протикает и лампочка выключится.

Код: Выделить всё

 if (key_on_flag==1)                // Запуск таймера включения кнопки (антидребезг);
         {
             tic_tac++;
             m_sec++;

         if (m_sec==999)
             {
                    m_sec=0;
                    sec++;

                if (sec==59)
                 {
                    sec=0;
                    minutes++;

                        if (minutes==59)
                            {
                                minutes=0;
                                hours++;
                            if (hours == 5)
                              {
                                hours=0;
                       }
                     }
                 }
             }
         }
               else { tic_tac=0;  m_sec=0; }
О.... Пока писал, отработало!!! =) Оптимальнее будет работать с большим числом? Или наделать циклов?
[color=#4080FF]- Бежит этот подлец-электрон, а вокруг его масса (аж 10 в 23й) штук ионов кремния и 10 в 15й ионов примеси и он, подлец, взаимодействует![/color]
Контактная информация:
Мучитель микросхем
Аватара пользователя
Сообщения: 414
Зарегистрирован: Ср янв 26, 2011 13:43:30
Откуда: С того берега моря

Сообщение Jman »

Всем привет. Девайс собрал, но пока не устанавливал. На столе работает отлично. Тут такое дело. Я захотел переписать код в Atmel studio, компиллируется без ошибок, но не работает нормально. Может где-то напутал с битами входов выходов (в Atmel Studii как-то по другому все =)) Помогите пожалуйста найти ошибку.

Код: Выделить всё

/*
 * pir_control.c
  * PORTB3			                        // Bulb out, log 1;
 * PINB0							// PIR-sensor, zero active level;
 * PINB1							// Light switch, zero active level;
 */ 
 //PINB &_BV(PINB0)
 //(PINB &_BV(PINB1)
 //PORTB &= ~_BV(1<<3)
#ifndef F_CPU
	#define F_CPU 9600000L
#endif	
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>			
//#define OUT PORTB
//#define PIR (PINB &_BV(PINB0)) 
//#define KEY (PINB &_BV(PINB1))  
#define DEBOUNCE 2000
#define PIRDELAY 3000
#define PHOTOOFFSET 5000
#define FIRST_ADC_INPUT 1
#define LAST_ADC_INPUT 2
// Bandgap Voltage Reference: Off
#define ADC_VREF_TYPE ((0<<REFS0) | (0<<ADLAR))

//Global varibles;

volatile unsigned int adcScanningData[LAST_ADC_INPUT-FIRST_ADC_INPUT+1];
// Counters;
volatile unsigned int on=0, timeCounter=0, timeCounterDown=0;   
volatile unsigned char photoSeensor;
volatile unsigned char sensivity;
// switch flag;
volatile unsigned char keyFlag = 0;								
volatile unsigned int milliSeconds = 0, seconds = 0, minutes=0, hours=0;

// Prototype of functions; 

//peripherial initialisation;
void init (void);	
// ADC data read function;			
void adcInputsread (void);	
//main logic function;
void mainLogic (void);		

// Free running ADC interrupt; 

ISR(ADC_vect) 
{
	static unsigned char input_index=0;
	// Read the AD conversion result
	adcScanningData[input_index]=ADCW;
	// Select next ADC input
	if (++input_index > (LAST_ADC_INPUT-FIRST_ADC_INPUT))
	input_index=0;
	ADMUX=(FIRST_ADC_INPUT | ADC_VREF_TYPE)+input_index;
	// Delay needed for the stabilization of the ADC input voltage
	_delay_us(10);
	// Start the AD conversion
	ADCSRA|=(1<<ADSC);
}

// Timer0 compare interrupt; 

  ISR (TIM0_COMPA_vect) 
{
	// Counter for light switch;
	static unsigned char acNetCounter = 15;    
	// TCNT0=0x00;
	if((PINB &_BV(PINB1))==1)
	{
		// Read 1 state - switch is active;
		// Time checking;
		if(acNetCounter)
		{
			// time is not run;
			acNetCounter --;
		}
		else
		{
			// 15 mseconds switch is on;
			keyFlag = 0;
			// set the counter again;
			acNetCounter = 15;	
		}
	}
	else
	{
		// Read 0 - Switch is on;
		keyFlag = 1;
		// set the counter again;
		acNetCounter = 15;		  
	}
	// Start with switch / debounnce;
	if (keyFlag==1)               
	{
		timeCounter++;
		if (timeCounter>=DEBOUNCE)
		{
			timeCounter = DEBOUNCE;
			timeCounter++;

			if (milliSeconds==999)
			{
				milliSeconds=0;
				seconds++;

				if (seconds==59)
				{
					seconds=0;
					minutes++;

					if (minutes==59)
					{
						minutes=0;
						hours++;

						if (hours > 5)
						{
							hours=7;
						}
					}
				}
			}
		}
	}
	else
	{
		timeCounter=0;  milliSeconds=0; seconds = 0, minutes=0, hours=0;
	}

	// Switch on delay and Pir sensor debounce
	if ((PINB &_BV(PINB0)==0) && (keyFlag==0)&&(photoSeensor>=sensivity))   
	{
		on++;
	}
	else
	{
		on=0;
		//TCNT0=0;
	}
	if ((PINB &_BV(PINB0)==0) && (photoSeensor<sensivity) && (PORTB|=(1<<3)))
	timeCounterDown++;
	else timeCounterDown = 0;
	TCNT0=0x00;
  }


int main(void)
{ 
	init();
	PORTB &= ~(1<<3);

//  Main programm

while (1)
	{

	  // ADC read function(10bit);
      adcInputsread();
	  // Main logic function;          
      mainLogic();				
         
	}
	
}
// Initialisation microcontroller and peripherals;
void init (void)
{
	{
		// 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 B initialization
		// Function: Bit5=In Bit4=In Bit3=Out Bit2=In Bit1=In Bit0=In
		DDRB=(0<<DDB5) | (0<<DDB4) | (1<<DDB3) | (0<<DDB2) | (0<<DDB1) | (0<<DDB0);
		// State: Bit5=T Bit4=P Bit3=1 Bit2=T Bit1=P Bit0=T
		PORTB=(0<<PORTB5) | (1<<PORTB4) | (1<<PORTB3) | (0<<PORTB2) | (1<<PORTB1) | (0<<PORTB0);

		// ADC initialization
		// ADC Clock frequency: 150,000 kHz
		// ADC Bandgap Voltage Reference: Off
		// ADC Auto Trigger Source: Free Running
		// Digital input buffers on ADC0: On, ADC1: On, ADC2: On, ADC3: On
		DIDR0=(0<<ADC0D) | (0<<ADC2D) | (0<<ADC3D) | (0<<ADC1D);
		ADMUX=FIRST_ADC_INPUT | ADC_VREF_TYPE;
		ADCSRA=(1<<ADEN) | (1<<ADSC) | (1<<ADATE) | (0<<ADIF) | (1<<ADIE) | (1<<ADPS2) | (1<<ADPS1) | (0<<ADPS0);
		ADCSRB=(0<<ADTS2) | (0<<ADTS1) | (0<<ADTS0);

		// Timer/Counter 0 initialization
		// Clock source: System Clock
		// Clock value: 150,000 kHz
		// Mode: CTC top=OCR0A
		// OC0A output: Disconnected
		// OC0B output: Disconnected
		// Timer Period: 1 ms
		TCCR0A=(0<<COM0A1) | (0<<COM0A0) | (0<<COM0B1) | (0<<COM0B0) | (1<<WGM01) | (0<<WGM00);
		TCCR0B=(0<<WGM02) | (0<<CS02) | (1<<CS01) | (1<<CS00);
		TCNT0=0x00;
		OCR0A=0x95;
		OCR0B=0x00;

		// Timer/Counter 0 Interrupt(s) initialization
		TIMSK0=(0<<OCIE0B) | (1<<OCIE0A) | (0<<TOIE0);
		sei ();	
	}
}

void adcInputsread (void)
{
	// first channel value, PORTB2 ;
	photoSeensor=adcScanningData[0];
	 // second channel value, PORTB4;			  
	sensivity=adcScanningData[1];                
}

void mainLogic (void)
{
	  // switch state
	  unsigned char switchOn;					  
	  // Forbid global interrupts;
	  cli ();									
	  switchOn = keyFlag; 
	  // Allow global interrupts;
	  sei ();         
	  // AC switch priority;
	  if ((switchOn==1) && (timeCounter>=DEBOUNCE) && (hours<5)) 
	  {
		  PORTB |=(1<<3);
	  }

	  // PIR=0,Switch=1
	  if ((PINB &_BV(PINB0)==0)&&(photoSeensor>=sensivity)&&(on>=PIRDELAY))  
	  {
		  // Out is log 1;
		  PORTB |=(1<<3);             
	  }


	  else if ((PINB &_BV(PINB0)==0)&&(!switchOn||switchOn)&&(photoSeensor>=sensivity)&&(PORTB |=(1<<3)))
	  {
		  PORTB |=(1<<3);      
	  }


	  if ((PINB &_BV(PINB0)==0) && (photoSeensor<sensivity) && (PORTB |=(1<<3))&& timeCounter>PHOTOOFFSET)
	  {
		  PORTB &=~(1<<3);
	  }
	  else if (PINB &_BV(PINB0)==1)
	  {
		  PORTB &=~(1<<3);
	  }

}


[color=#4080FF]- Бежит этот подлец-электрон, а вокруг его масса (аж 10 в 23й) штук ионов кремния и 10 в 15й ионов примеси и он, подлец, взаимодействует![/color]
Контактная информация:
Мучитель микросхем
Аватара пользователя
Сообщения: 414
Зарегистрирован: Ср янв 26, 2011 13:43:30
Откуда: С того берега моря

Сообщение Jman »

Ребята помогите, проблема с АЦП.
Вот настройка Free running;

Код: Выделить всё

DIDR0=(0<<ADC0D) | (0<<ADC2D) | (0<<ADC3D) | (0<<ADC1D);
ADMUX=FIRST_ADC_INPUT | ADC_VREF_TYPE;
ADCSRA=(1<<ADEN) | (1<<ADSC) | (1<<ADATE) | (0<<ADIF) | (1<<ADIE) | (1<<ADPS2) | (1<<ADPS1) | (0<<ADPS0);
ADCSRB=(0<<ADTS2) | (0<<ADTS1) | (0<<ADTS0);
Вот его прерывание

Код: Выделить всё

#define BULB 3
#define FIRST_ADC_INPUT 1
#define LAST_ADC_INPUT 2
// Bandgap Voltage Reference: Off
#define ADC_VREF_TYPE ((0<<REFS0) | (0<<ADLAR))

volatile unsigned int adcScanningData[LAST_ADC_INPUT-FIRST_ADC_INPUT+1];
volatile char photoSeensor;
volatile char sensivity;

ISR(ADC_vect)
{
	static unsigned char input_index=0;
	// Read the AD conversion result
	adcScanningData[input_index]=ADCW;
	// Select next ADC input
	if (++input_index > (LAST_ADC_INPUT-FIRST_ADC_INPUT))
	input_index=0;
	ADMUX=(FIRST_ADC_INPUT | ADC_VREF_TYPE)+input_index;
	// Delay needed for the stabilization of the ADC input voltage
	_delay_us(10);
	// Start the AD conversion
	ADCSRA|=(1<<ADSC);
}
Вот функция опроса двух каналов

Код: Выделить всё

void adcInputsread (void)
{
	// first channel value, PORTB2 ;
	photoSeensor=adcScanningData[1];
	// second channel value, PORTB4;
	sensivity=adcScanningData[0];
}
Вот основной код для проверки. Если напряжение на входе больше напряжения порога (на втором входе) Включаем Пин.
Если нет, то выключаем.

Код: Выделить всё

if (photoSeensor>=sensivity) 
	{
		// Out is log 1;
		PORTB |=(1<<BULB);
	}
	else if(photoSeensor<sensivity) PORTB &=~(1<<BULB);
Моделирую в протеусе, и там происходит следующее. Устанавливаю опорное напряжение (sensivity) потенциометром и фиксирую. И начинаю от нижнего края потенциометра, который посажен на вход (photoSeensor) двигать ползунок к большему значению. Выход у меня начинает загораться хаотично при движении ползунка в любую сторону, хотя должен строго выше опорного напряжения срабатывать, а ниже опорного отключаться. Что это происходит?
[color=#4080FF]- Бежит этот подлец-электрон, а вокруг его масса (аж 10 в 23й) штук ионов кремния и 10 в 15й ионов примеси и он, подлец, взаимодействует![/color]
Контактная информация:
Ответить

Вернуться в «AVR»