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

Не Понятное Поведение Ацп В Attiny13


ranthunt

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

Суть проблемы такова. Tiny13 замеряет напряжение на ацп и в зависимости от него ждет 1-20 минут. В прерывании таймера0 выполняется:

time_cnt++;

time_tmp=ADC_VAL_PWM*89;

if (time_cnt>time_tmp){LED_ON; }

значение ацп в главном цикле измеряется так:

unsigned int read_adc(unsigned char adc_input)

{

ADMUX=adc_input ;

_delay_us(100);

ADCSRA|=(1<<ADSC);

while ((ADCSRA & (1<<ADIF))==0);

ADCSRA|=(1<<ADIF);

return ADCW;

}

В главном цикле:

while (1) {

asm("cli");

read_adc(0x03);

ADC_VAL_PWM=read_adc(0x03);

asm("sei");

}

Так вот,

time_cnt++;

time_tmp=ADC_VAL_PWM*89;

if (time_cnt>кокое то заранее посчитанное число){LED_ON; }

РАБОТАЕТ

а то как в начале сообщения нет, такое чувство что переполнение переменной но типы взяты с запасом...

Во вложении весь файл.

Бьюсь уже неделю, перепробовал все... СПАСАЙТЕ

main.rar

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

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

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

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

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

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

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

У вас МК занят только тем, что ждет окончания преобразования АЦП. И при этом вы еще зачем-то запретили прерывания. У МК просто нет времени заняться прерыванием таймера. Уберите запрет прерываний из цикла - он там абсолютно не нужен. И вообще сделайте отдельное прерывание по готовности данных АЦП и не тратьте время МК на бесполезное ожидание.

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

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

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

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

#include <avr/io.h>
#include <stdint.h>
#define F_CPU 1200000
#include <util/delay.h>
#include <avr/interrupt.h>
#define PIN_LED 2
#define PIN_OUT 0
#define PIN_PWM 3
#define PIN_TIME 4
#define LED_ON PORTB&=~(1<<PIN_LED);
#define LED_OFF PORTB|=(1<<PIN_LED);
#define PWM_OUT_EN DDRB|=(1<<PIN_OUT);
#define PWM_OUT_DS DDRB&=~(1<<PIN_OUT);
volatile unsigned char ev_BUTTON=0;
volatile unsigned char ev_TIMER=0;
volatile unsigned  char PWM_VAL;
volatile unsigned int ADC_VAL_PWM;
volatile uint16_t ADC_VAL_TIME;
unsigned long time_cnt;
uint64_t time_tmp;
ISR(ADC_vect)
{
ADCSRA|=(1<<ADIF);
}
unsigned int read_adc(unsigned char adc_input)
{
ADMUX=adc_input ;
// Delay needed for the stabilization of the ADC input voltage
_delay_us(100);

ADCSRA|=(1<<ADSC);

while ((ADCSRA & (1<<ADIF))==0);
ADCSRA|=(1<<ADIF);
return ADCW;
}
ISR(TIM0_OVF_vect)
{

//819=3.99V  860=4.2V  950=4.6V

 if (ADC_VAL_PWM>860) {ev_BUTTON=1;} else{
   if (ADC_VAL_PWM>819) {ADC_VAL_PWM=819;}   
PWM_VAL=(unsigned char)((ADC_VAL_PWM>>2)+50);
OCR0A=PWM_VAL;	  
 }


time_cnt++;

if  (ev_TIMER){
 time_tmp=ADC_VAL_TIME*89;

 if (time_cnt>time_tmp){LED_ON; PWM_OUT_DS;ev_TIMER=0;}
}


};
int main(void)
{
   DDRB=(1<<PIN_LED)|(1<<PIN_OUT);
PORTB=0x00;


ADMUX=0x03;
ADCSRA|=(1<<ADEN)|(1<<ADPS1);//|(1<<ADATE);
DIDR0|=(1<<ADC2D)|(1<<ADC3D);

//ADCSRB|=(1<<ADTS2);

TCCR0A|=(1<<COM0A1)|(1<<WGM00)|(1<<WGM01);
TCNT0=0x00;
OCR0A=0x7F;//128
TIMSK0|=(1<<TOIE0);

TCCR0B|=(1<<CS00)|(1<<CS01); // CLK/64=(9.6/8)/64

asm("sei");
LED_ON;

PWM_OUT_DS;

ADCSRA|=(1<<ADSC);


   while (1)
   {
 asm("cli");

 read_adc(0x03);
 ADC_VAL_PWM=read_adc(0x03); 
 read_adc(0x02);
 ADC_VAL_TIME=read_adc(0x02);

 asm("sei");

 if (ev_BUTTON) {time_cnt=0x00; ev_TIMER=1; LED_ON; PWM_OUT_EN; ev_BUTTON=0;}  

 if (ev_TIMER){LED_ON; _delay_ms(250); LED_OFF; _delay_ms(250);}

   }
}

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

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

#define F_CPU 1200000
TCCR0B|=(1<<CS00)|(1<<CS01); // CLK/64=(9.6/8)/64
ADCSRA|=(1<<ADEN)|(1<<ADPS1);

Так какая у вас тактовая частота, 12 МГц или 9.6?

Предделитель АЦП 0b010 означает деление 1:4, то есть от 3 до 2.4 МГц (смотря какая тактовая частота), а то время, как АЦП не работает на частотах выше 1 МГц, а оптимально 50 - 200 кГц.

Ну и традиционно - форматирование кода ужасно.

Ругался на отсутствие форматирования исходного кода (включая отсутствие осмысленных комментариев и наличие неубранного после конфигуратора мусора) не менее 15 раз.

Часть моих наработок.

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

1. Возможно потребуется задержка после переключения канала

2. Первые одно или два измерения не принимаем за действительные, только следующие за ними

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

Частота 1.2Мгц полученная как 9.8/8 что есть заводские настройки тиньки.

Задержка после переключения есть, первое измерение не учитывается. Все это есть в коде.

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

Видимо, даташит в руки не дается.

14. Analog to Digital Converter

14.1 Features

• 10-bit Resolution

• 0.5 LSB Integral Non-linearity

• ± 2 LSB Absolute Accuracy

• 13 - 260 μs Conversion Time

13 мкс это примерно 77 тысяч выборок в секунду. Время одного преобразования 13 тактов АЦП, так что тактовая частота не должна превышать 1 МГц.

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

ADCSRA|=(1<<ADEN)|(1<<ADPS1);//|(1<<ADATE);
Это делитель 1:4 а не 1:8. Или вы выложили не тот код, который тестируете?

Ну и #define F_CPU из кода тогда стоит убрать и перенести в настройки проекта.

Ругался на отсутствие форматирования исходного кода (включая отсутствие осмысленных комментариев и наличие неубранного после конфигуратора мусора) не менее 15 раз.

Часть моих наработок.

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

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

Не совсем понял, разве ADCSRA|=(1<<ADEN); не достаточно для включения АЦП?

Это делитель 1:4
согласен, все так. Не понимаю откуда вы взяли что настройка на 1:8, в коде не слова про это. У меня получается что частота АЦП 300 КГц и на сколько я понял
13 тактов АЦП
это уже про те такты что после делителя?

Поправьте если что не так.

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

Направление проблемы поменялось :buba:

Как и предполагал похоже на переполнение типа переменной.

time_tmp=ADC_VAL_TIME*89;

компилятор не ругается.

time_tmp=1024*89;

компилятор выдает предупреждение "Warning integer overflow in expression [-Woverflow] " что говорит о переполнение типа, НО переменная объявлена

volatile unsigned long time_tmp;

Откуда берется переполнение типа?! Пишу в Atmel Studio 7

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

Оптимизация включена? Обычно константе компилятор присваивает определенный тип, возможно их произведение не влазит в unsigned long

Любой, заслуживающий внимания, опыт приобретается себе в убыток...

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

Оптимизация -О2. Переменная объявлена как unsigned long в нее не может не влезть 1024*89

Смущает что компилятор пишет "Warning INTEGER overflow in expression [-Woverflow] " пишет что INTEGER хотя оно LONG

Возможно ли что где то есть какое то ограничения на максимальный тип переменных в настройках проекта/компилятора?

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

Переменная объявлена как unsigned long в нее не может не влезть 1024*89

Причем тут 1024*89. Речь о размере произведения тип_константы*тип_константы, если даже не приведенный_тип_константы(способный хранить тип_константы*тип_константы)*тип_константы

Любой, заслуживающий внимания, опыт приобретается себе в убыток...

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

Ну даже если считать так как вы пишете, то при не заданном типе жестко (для константы) компилятор берет минимальный в который константа влезает (иначе был бы не правильный компилятор )) ) int * char меньше long

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

он берет, насколько помню, тип int если константа меньше 32768, и long int (он же long long) если больше. К тому же не стоит исключать приведение типов. Т.е. возможен вариант long_int*int. Нужно читать доки на компилятор. В любом случае, гипотетическую проблему компилятор видит, но это не значит что она есть при произведении 1024*89

Любой, заслуживающий внимания, опыт приобретается себе в убыток...

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

Итак тестирования девайса дали следующий результат. По одной из проблем-положительный, что радует :crazy:

time_tmp=(unsigned long)ADC_VAL_TIME*89;

Отрабатывает все четко. При этом

time_tmp=(unsigned long)(ADC_VAL_TIME*89);

снова даёт переполнение.

Не понятно почему приходится указывать 2 раза размер переменной. time_tmp,ADC_VAL_TIME обе переменные unsigned long и зачем дополнительные пляски на костях не ясно. Если кто знает разъясните.

Осталось победить влияние показаний двух каналов АЦП друг на друга (если эта проблема еще осталась). Тесты продолжаются :umnik2:

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

Приведите еще раз полный код последней редакции

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

Любой, заслуживающий внимания, опыт приобретается себе в убыток...

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

time_tmp=(unsigned long)ADC_VAL_TIME*89;

В данном примере сначала ADC_VAL_TIME приводится к unsigned long и умножается на 89. Этот вариант правильный.

time_tmp=(unsigned long)(ADC_VAL_TIME*89);

А здесь, сначала ADC_VAL_TIME умножается на 89 (оставаясь uint16_t), а потом приводится к unsigned long — отсюдова и переполнение

Читайте матчасть — язык С, приведение типов.

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

Собственно так и есть, но автор утверждает

time_tmp,ADC_VAL_TIME обе переменные unsigned long

Потому и надо увидеть весь код

Любой, заслуживающий внимания, опыт приобретается себе в убыток...

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

согласен, все так. Не понимаю откуда вы взяли что настройка на 1:8, в коде не слова про это. У меня получается что частота АЦП 300 КГц и на сколько я понял

А это кто писал?

Частота 1.2Мгц полученная как 9.8/8 что есть заводские настройки тиньки.

300`000 отсчетов в секунду АЦП не тянет, максимум 77`000. Кстати, 300 кГц у меня не получается, только 188 кГц, что все равно много. Как вы считали?
это уже про те такты что после делителя?

Поправьте если что не так.

Да, 13 импульсов тактирования АЦП. И именно их частота не должна превышать 1 МГц. Тогда скорость съема аналогового сигнала будет не более 77 тысяч отсчетов в секунду.

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

Ругался на отсутствие форматирования исходного кода (включая отсутствие осмысленных комментариев и наличие неубранного после конфигуратора мусора) не менее 15 раз.

Часть моих наработок.

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

  • 1 год спустя...

Столкнулся с такой странностью: Ацп выдаёт все нули до входного напряжения около 2 вольт, потом биты меняются "по теории", перепробовал три микросхемы - во всех такая странность. Кто что подскажет?

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

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

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

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

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

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

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

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

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

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

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