VccRead на ATTiny13

HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013

Всем привет. Для реализации одной задумки нужно как-то считать напряжение питание микроконтроллера ATTiny13. Недавно случайно наткнулся на статью где вроде бы всё хорошо, попробовал код на ардуино - работает:

http://www.youtube.com/watch?v=EZbOaSX29Xo

Но на написал простенький скетч для тиньки:



static int vccRead(byte us =250) {
  ADMUX = 1<<REFS0; // опорное напряжение - Vcc
  ADMUX |= 0x0E;    // объект измерения - внутренний источник
  // стабилизированного напряжения 1.1В
  delayMicroseconds(us);

  ADCSRA |= 1<<ADSC;         // запуск АЦ-преобразования
  while(ADCSRA & (1<<ADSC)); // и ожидание его завершения
  word x = ADC;
  return x ? (1100L * 1023) / x : -1;
}

void setup() {
  pinMode(4, OUTPUT);    
}

void loop() {
  digitalWrite(4, HIGH);   
  delay(vccRead() / 10);               
  digitalWrite(4, LOW);    
  delay(vccRead() / 10);       
}

При программной эмуляции ничего не происходит, тоесть функция vccRead() не имеет никакого значения.

Наперед Спасибо.

HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013

Всё разобрался:

static int vccRead(byte us =250) {
  ADMUX = 1<<REFS0; // опорное напряжение - Vcc
  ADMUX |= 0x0E;    // объект измерения - внутренний источник
  // стабилизированного напряжения 1.1В
  delayMicroseconds(us);

  ADCSRA |= 1<<ADSC;         // запуск АЦ-преобразования
  while(ADCSRA & (1<<ADSC)); // и ожидание его завершения
  word x = ADC;
  return x ? (1100L * 1023) / x : -1;
}

void setup() {
  pinMode(4, OUTPUT);    
}

void loop() {
int v = vccRead() / 1000 ;
  for(byte b = 1; b < v; b++) // мигання індикатора роботи 4
  {
    PORTB |= (1<<4);  
    delay(1000);   
    PORTB &= ~(1<<4);
    delay(1000);
  } 
  v = 0;
  delay(5000);  
  }

Кстати интересная функция... особенно когда питаете микроконтроллер от батареи и не хотите чтобы он убил её.

HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013

Хотя работает уже на макетке нетак как в протеусе, мигает то 18 раз то 3 раза то 10 а должно примерно один раз на 1 вольт, тоесть если напряжение питания 3.5 В то мигает 3 раза если 5 - 5...

Andrey_Y_Ostanovsky
Offline
Зарегистрирован: 03.12.2012
HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013

Я в Английском не силён, нашёл код:



long readVcc() {
  // Read 1.1V reference against AVcc
  // set the reference to Vcc and the measurement to the internal 1.1V reference
  #if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
    ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
  #elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
    ADMUX = _BV(MUX5) | _BV(MUX0);
  #elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
    ADMUX = _BV(MUX3) | _BV(MUX2);
  #else
    ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
  #endif  
 
  delay(2); // Wait for Vref to settle
  ADCSRA |= _BV(ADSC); // Start conversion
  while (bit_is_set(ADCSRA,ADSC)); // measuring
 
  uint8_t low  = ADCL; // must read ADCL first - it then locks ADCH  
  uint8_t high = ADCH; // unlocks both
 
  long result = (high<<8) | low;
 
  result = 1125300L / result; // Calculate Vcc (in mV); 1125300 = 1.1*1023*1000
  return result; // Vcc in millivolts
}

void setup() {
 
}

void loop() {
  readVcc();
  
}

Вставил в IDE выбрал ATtiny13 и вот что мне среда выдаёт:

 

sketch_jul30d.ino: In function 'long int readVcc()':
sketch_jul30d:11: error: 'MUX3' was not declared in this scope
sketch_jul30d:11: error: 'MUX2' was not declared in this scope

Andrey_Y_Ostanovsky
Offline
Зарегистрирован: 03.12.2012

Ну, значит ваш вариант не подходит под "else" и надо разбираться в регистрах самостоятельно...

http://html.alldatasheet.com/html-pdf/80274/ATMEL/ATTINY13/4483/34/ATTIN...

Ключевые слова: "bandgap reference"

HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013

И на том спасибо :)

Вижу что у меги есть нога AREF pin вот походу от неё мега и узнаёт напряжение питания. В тини такой нету.

__Alexander
Offline
Зарегистрирован: 24.10.2012

А можно ссылку где вы взяли вот эту недокументированную возможность измерения внутреннего источника и для чего его в общем измерять?

  ADMUX |= 0x0E;    // объект измерения - внутренний источник  // стабилизированного напряжения 1.1В

в оригинальном ДШ такого нет. Есть только mux0 и mux1.

 

HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013
HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013

Ответил автор статьи, к сожалению невозможно таким способом узнать напряжение питания. В голову приходит только DC-DC конвертор на 5 В...

sva1509
Offline
Зарегистрирован: 07.12.2012

Доброго времени суток !

На ATtiny13 не получится. Идея данного решения основывается на том что АЦП настроен для замера между AVcc и Aref.

AVcc в arduino подключен на 5В тоесть на питание. Внутри atmega есть стабилизированный источник 1.1В. Самое главное 328ая можен подвключить на вход АЦП этот внутренний источник, а ATTiny13 НЕТ. 328ая сделав замер до 1.1В пересчитав получает полную величину AVcc - тоесть питания.

HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013

Спасибо за помощь.

HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013

Насколько я понимаю если не получится сделать программно то должно получится аппаратно? Подскажите как пожалуйста.

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

Для начала интересует сколько у вас литиевых батарей. если одна то ставите lowdrop стабилизатор например HT7133 на 3.3В. Падение на нем всего 0,1В, но максимальный ток 30мА. Для тиньки хватит 30 мА, а вот выходной полевик питать уже от батареи (если я правильно понял вы спрашиваете для проекта велофары).

Правда рабочее напряжение всего получается 3,4-4,2В. Есть также HT7130 на 3В , который лучше подойдет и рабочее напряжение полчается 3,1-4,2. Батарею полнее используете. Так как питание Vcc у вас стабильное через делитель измеряйте напряжение на батарее и вам больше не нужен внутренний опорник

только не забудьте настроить фьюзы Bodlevel чтобы у вас тинька не отрубалась при питании 3 или 3.3 В

можете поставить 2.7В или вообще отключить

и еще. полевиком напрямую с тиньки лучше не управлять. во первых ток ограничен, будет плавать напряжение питания, во вторых 3В(незнаю сколько падение на внутренних транзисторах тиньки) может быть недостаточно чтобы открыть полевик. сделайте небольшой драйвер

хотя если светодиды не очень мощные можно применить IRLML2502 с которым может и получится запустить без драйвера

надо проверять

HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013

Вот график моего транзистора которого я выпаял из старой материнки:

PHB55N03LT.
Я тут подумал, а что если использовать стабилитрон на напряжение 3.3В, когда напряжение достигнет 3.3 то значение АЦП будет 1023 что будет сигнализировать тиньке что пора или уменьшать режим или заснуть вообще...

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

у вашего транзистора емкость затвора выше 1230пф и тинька с таким слабым стабилизатором может просто не открыть полностью транзистор, да и питание будет скакать и работать все нестабильно будет

у IRLML2502 емкость 740пф кажется

а вот со стабилитроном честно сказать не понял

HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013

Ок, спасибо, правда этот в смд корпусе, а я всё делаю грубо и на макетной плате, с моим паяльником смд это убийство.

jeka_tm пишет:

а вот со стабилитроном честно сказать не понял

Питать планирую тиньку от того же источника, без стабов, и на один АЦП подать стабилизированное напряжение в 3.3 В которое хочу получить при помощи стабилитрона, АЦП будет постоянно возвращать значение меньше 1023-х, ведь там напряжение меньше напр. питания, когда напряжение достигнет напряжения стабилизации стабилитрона то уже значение ацп приблизится до 1023...
 Я ведь верно размышляю?

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

вы что паяете 60 ватным советстким паяльником?

а насчет стабилитрона неплохая идея, само напряжение питания тяжело будет измерять, нужна апроксимация, а вот просто отследить что достигло напряжение при котором выключить подойдет. но это нужно постоянно ацп гонять. хотя вместо стабилитрона я бы взял лучше TL431 например. у него зависимость от температуры меньше (вы же не дома будете использовать устройство)

а можно вообще принцип поменять. зачем измерять напряжение ацп.

поставьте TL431, переменным резистором настройте уровень срабатывания. и как только напряжение достигнет заданного уровня на выходе получите 0 или 1 (смотря какую схему сделаете). и обрабатывайте сколько хотите. и тиньку разгрузите

 

HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013

TL431 - отличный выход из ситуации, но это лишние детали, на данном этапе буду использовать тиньку, она любит работать, мощи достаточно... но всё равно спасибо.
Не задаюсь целью сделать точную индикацию напряжения, мне нужно отследить только 2 значения, первое когда нужно уменьшить уровень, пока понятия как это программно сделать немею... ну до этого ещё долго.

ЗЫ 65 ваттним паяльником паяю :)