Страница 1 из 1
Управление реле на Atmega8
Добавлено: Сб июн 08, 2013 10:42:33
yakidiman
Доброго времени суток. Делаю устройство для управления релюшками на atmege8. Смысл в том, что исходными сигналами для включения и отключения реле являются два сигнала с АЦП. Так в целом программу написал, в протеусе промоделировал, все отлично. Но когда собрал на макетке и подаю питание, то на нужных мне пинах сразу появляется "1". И это независимо, что на входе АЦП, даже подтягивал эти входы к земле. Вот сама программа, ну а схема я думаю тут и не нужна, т.к. проще некуда.
Помогите пожалуйста, разобраться где собака порылась.
Спойлер
#define F_CPU 1000000
#include <avr/io.h>
#include <avr/iom8.h>
# include <util/delay.h>
#include <AVR/interrupt.h>
#define sei()
// Опорное напряжение - ножка AREF
#define ADC_VREF_TYPE 0b00000000
unsigned int ADCdata;
unsigned int ADCdata1;
void ADC1(ADCdata);
unsigned int ADCRead(unsigned char adc_input) // Подпрограмма считывания данных с АЦП
{
ADMUX = adc_input | ADC_VREF_TYPE;
//Задержка для стабилизации АЦП
_delay_us(50);
// Запускаем АЦП
ADCSRA |= 0x40;
while ((ADCSRA & 0x10) == 0); // Ждем флага окончания преобразования
ADCSRA |= 0x10;
return ADCW;
}
int main(void)
{
DDRD=0xFF;
PORTD=0x00;
/*** Настройка АЦП ***/
ADCSRA |= (1 << ADEN)|(1 << ADPS2)|(1 << ADPS1)|(0 << ADPS0);
while(1)
{
// вход ADC0
//включение, настройка АЦП
ADCSRA |= (1 << ADEN)|(1 << ADPS2)|(0 << ADPS1)|(1 << ADPS0);
ADMUX |= (0 << REFS1)|(0 << REFS0)|(0 << MUX0)|(0 << MUX1)|(0 << MUX2)|(0 << MUX3);
_delay_us(50);
ADCSRA |= (1 << ADSC); //начало преобразования
while((ADCSRA&(1 << ADIF))== 0); //ждем прерывания
ADCSRA |= (1 << ADIF);
ADCdata = ADCRead(0);// Запись результата с первого порта АЦП
// вход ADC1
ADMUX |= (0 << REFS1)|(0 << REFS0)|(1 << MUX0)|(0 << MUX1)|(0 << MUX2)|(0 << MUX3);
_delay_us(50);
ADCSRA |= (1 << ADSC); //начало преобразования
while((ADCSRA&(1 << ADIF))== 0); //ждем прерывания
ADCSRA |= (1 << ADIF);
ADCdata1 = ADCRead(1); //запись результата
ADCSRA |= (0 << ADEN); //выключение АЦП
if ((ADCdata >= 341)&&(ADCdata1 >= 10)) // 0.625V
{
PORTD = 0b00000100;
}
else
{
PORTD=0b00000000;
}
//_delay_ms(30);
}
}
Re: Управление реле на Atmega8
Добавлено: Сб июн 08, 2013 12:28:35
shads
Не вникал особо, но в глаза бросилось что вы не правильно сбрасываетет биты.....
например у вас в цикле крутится: включение канала 1
ADMUX |= (0 << REFS1)|(0 << REFS0)|(1 << MUX0)|(0 << MUX1)|(0 << MUX2)|(0 << MUX3);
потом включение канала 0
ADMUX |= (0 << REFS1)|(0 << REFS0)|(0 << MUX0)|(0 << MUX1)|(0 << MUX2)|(0 << MUX3);
но так вы не включите канал 0, т.к. этой командой бит MUX0 не сбросится (и вообще эта команда абсолютно ничего не делает с содержимым ADMUX, что бы там не находилось).....
то же самое и тут:
ADCSRA |= (0 << ADEN); //выключение АЦП
так бит не сбросиш.....
не знаю как это влияет на работоспособность программы, но на заметку возьмите.....
А это еще зачем?
#define sei()
Re: Управление реле на Atmega8
Добавлено: Сб июн 08, 2013 13:12:23
Vov123
это какой-то бред,а не программа.

Re: Управление реле на Atmega8
Добавлено: Сб июн 08, 2013 13:27:41
shads
Как то так надо:
Код: Выделить всё
#define F_CPU 1000000
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
unsigned int ADCdata;
unsigned int ADCdata1;
unsigned int ADCRead(unsigned char adc_input);
int main(void)
{
DDRD = 0xFF;
//настройка ADC
ADMUX = 0; //внешний опорный источник
ADCSR = (1<<ADEN)|(1<<ADPS2)|(0<<ADPS1)|(1<<ADPS0);
while(1)
{
ADCdata = ADCRead (0<<MUX0); //вход ADC0
ADCdata1 = ADCRead (1<<MUX0); //вход ADC1
if ((ADCdata >= 341)&&(ADCdata1 >= 10)) // 0.625V //анализ результата
PORTD = 0b00000100;
else
PORTD = 0b00000000;
}
}
unsigned int ADCRead(unsigned char adc_input) // Подпрограмма считывания данных с АЦП
{
ADMUX = adc_input;
_delay_us(50); //Задержка для стабилизации АЦП
ADCSR |= (1<<ADSC); //запустить преобразование
while (ADCSR & (1<<ADSC)){} //крутимся в цикле до конца замера
return (ADCL + (ADCH<<8));
}
Re: Управление реле на Atmega8
Добавлено: Сб июн 08, 2013 13:40:57
Vov123
Свой вариант предложу,только настройки АЦП немного другие.ТС может легко их исправить.
Код: Выделить всё
#define F_CPU 1000000
#include <avr/io.h>
#include <util/delay.h>
unsigned int ADCdata;
int main(void)
{
DDRD=0xFF;
PORTD=0x00;
//опорное напряжение от питания,выравнивание в право(10бит)
//ручное преобразование,вход на ADC3
ADCSRA=0b10000111;
ADMUX=0b01000011;
while(1)
{
ADCSRA |= (1 << 6); //начало преобразования
loop_until_bit_is_clear(ADCSRA,6);
ADCdata = ADCW;
if ((ADCdata >= 10)&&(ADCdata <= 341))PORTD = 0b00000100; // 0.625V
else
PORTD=0b00000000;
_delay_ms(500);
}
}
Re: Управление реле на Atmega8
Добавлено: Пн июн 10, 2013 09:03:05
yakidiman
shads писал(а):Как то так надо:
Код: Выделить всё
#define F_CPU 1000000
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
unsigned int ADCdata;
unsigned int ADCdata1;
unsigned int ADCRead(unsigned char adc_input);
int main(void)
{
DDRD = 0xFF;
//настройка ADC
ADMUX = 0; //внешний опорный источник
ADCSR = (1<<ADEN)|(1<<ADPS2)|(0<<ADPS1)|(1<<ADPS0);
while(1)
{
ADCdata = ADCRead (0<<MUX0); //вход ADC0
ADCdata1 = ADCRead (1<<MUX0); //вход ADC1
if ((ADCdata >= 341)&&(ADCdata1 >= 10)) // 0.625V //анализ результата
PORTD = 0b00000100;
else
PORTD = 0b00000000;
}
}
unsigned int ADCRead(unsigned char adc_input) // Подпрограмма считывания данных с АЦП
{
ADMUX = adc_input;
_delay_us(50); //Задержка для стабилизации АЦП
ADCSR |= (1<<ADSC); //запустить преобразование
while (ADCSR & (1<<ADSC)){} //крутимся в цикле до конца замера
return (ADCL + (ADCH<<8));
}
Все также, на третьем пине D "1" появляется сразу же, а в протеусе все четко.
Re: Управление реле на Atmega8
Добавлено: Пн июн 10, 2013 09:28:44
metan
yakidiman писал(а):Все также, на третьем пине D "1" появляется сразу же
А где вы сказали процессору, что там ноль обязан быть?
Вот Vov123 в своей программе сказал.
Re: Управление реле на Atmega8
Добавлено: Пн июн 10, 2013 09:58:41
yakidiman
metan писал(а):yakidiman писал(а):Все также, на третьем пине D "1" появляется сразу же
А где вы сказали процессору, что там ноль обязан быть?
Вот Vov123 в своей программе сказал.
Когда я сказал процессору в начальном состоянии должно быть ноль, он переходит в неопределенное состояние, нужный мне порт тоже так же
Re: Управление реле на Atmega8
Добавлено: Пн июн 10, 2013 12:48:04
ibiza11
ребят, харош курить, разговоры с процессорами до хорошего не доведут

пиши PORTD = 0; там где ты DDRD определяешь.
Re: Управление реле на Atmega8
Добавлено: Пн июн 10, 2013 14:28:41
yakidiman
проблема с 0 и 1 решилась, появилась другая проблема. Теперь когда входы АЦП подтянуты на землю, все нормально, но стоит поставить на ацп просто провода от датчиков не подключая сами датчики, то на том же пине D3 появляется 2,5В. Также при подключенных датчиках.
Re: Управление реле на Atmega8
Добавлено: Пн июн 10, 2013 15:10:20
ibiza11
Посмотрите осциллографомскопом форму импульсов на выходе 3. Висящий в воздухе вход АЦП может давать все что угодно.
Re: Управление реле на Atmega8
Добавлено: Вт июн 11, 2013 02:39:28
shads
metan писал(а):А где вы сказали процессору, что там ноль обязан быть?
Вот Vov123 в своей программе сказал.
ibiza11 писал(а):пиши PORTD = 0; там где ты DDRD определяешь.
Программа крутится в этом цикле, и будет там 0 или 1 зависит от результатов измерения АЦП, а не от того что пропишеш при старте.....
Код: Выделить всё
while(1)
{
ADCdata = ADCRead (0<<MUX0); //вход ADC0
ADCdata1 = ADCRead (1<<MUX0); //вход ADC1
if ((ADCdata >= 341)&&(ADCdata1 >= 10)) // 0.625V //анализ результата
PORTD = 0b00000100;
else
PORTD = 0b00000000;
yakidiman писал(а):проблема с 0 и 1 решилась
Ну так хоть намекни уж в чем проблема была.... небось с опорным напряжением накосячил.....
Re: Управление реле на Atmega8
Добавлено: Вт июн 11, 2013 08:02:54
ibiza11
shads писал(а):Программа крутится в этом цикле, и будет там 0 или 1 зависит от результатов измерения АЦП, а не от того что пропишеш при старте.....
А Вы не видите, что перед выводом в порт ожидается два преобразования АЦП? За это время светодиод может моргнуть (продолжительность зависит от времени преобразования АЦП), поскольку начальное значение явно не задано. До окончания преобразования в порту будет именно то, что вывели при инициализации. Все переменные должны быть заданы явно. Пишите правильно, раз советы даете.
Re: Управление реле на Atmega8
Добавлено: Вт июн 11, 2013 09:01:27
yakidiman
shads писал(а):metan писал(а):А где вы сказали процессору, что там ноль обязан быть?
Вот Vov123 в своей программе сказал.
ibiza11 писал(а):пиши PORTD = 0; там где ты DDRD определяешь.
Программа крутится в этом цикле, и будет там 0 или 1 зависит от результатов измерения АЦП, а не от того что пропишеш при старте.....
Код: Выделить всё
while(1)
{
ADCdata = ADCRead (0<<MUX0); //вход ADC0
ADCdata1 = ADCRead (1<<MUX0); //вход ADC1
if ((ADCdata >= 341)&&(ADCdata1 >= 10)) // 0.625V //анализ результата
PORTD = 0b00000100;
else
PORTD = 0b00000000;
yakidiman писал(а):проблема с 0 и 1 решилась
Ну так хоть намекни уж в чем проблема была.... небось с опорным напряжением накосячил.....
Да, проблема была именно в этом, я неправильное опорное напряжение подавал))) Кстати, и моя и ваша программа отлично работают. Все нужные мне биты АЦП сбрасываются. Так что спасибо!
Re: Управление реле на Atmega8
Добавлено: Вт июн 11, 2013 09:03:26
yakidiman
ibiza11 писал(а):shads писал(а):Программа крутится в этом цикле, и будет там 0 или 1 зависит от результатов измерения АЦП, а не от того что пропишеш при старте.....
А Вы не видите, что перед выводом в порт ожидается два преобразования АЦП? За это время светодиод может моргнуть (продолжительность зависит от времени преобразования АЦП), поскольку начальное значение явно не задано. До окончания преобразования в порту будет именно то, что вывели при инициализации. Все переменные должны быть заданы явно. Пишите правильно, раз советы даете.
Сейчас все работает. Работает и начальным заданием порта D и без него.