ATtiny13A 101 применение

Delphin911
Offline
Зарегистрирован: 25.12.2019

Народ, не кидайтесь тапками, старательно читал форум, но не хватило терпения. Хочу для начала только теоретический вопрос по Attiny13 задать. Одни и те же выводы у нее могут быть и цифровыми и аналоговыми? Судя по распиновке в даташите получается, что выводы PB5, PB2, PB4 и PB3 это аналоговые A0, A1, A2 и A3 соответственно(ADCX)? Ну т.е. в скетче мы их указываем как A0, A1, A2 и A3. А выводы PB0, PB1, PB2, PB3, PB4 и PB5 соответственно цифровые порты 0, 1, 2, 3, 4 и 5(PCINTX). При этом PB0 и PB1 поддерживают ШИМ (AINX). Или я не до конца понял распиновку?

Так же не до конца понял обозначения dW, CLKI, T0, INTX. Хотя dW, как и SCK, MISO, MOSI используются при программировании через Ардуино (возможно и не только).

Ну RESET вроде понятно, но тоже не разобрался каким уровнем сброс осуществляется. Туго у меня с английским, а Datasheet на нем родимом.

Или может ссылочку дайте, где об этом по русски почитать можно.

Спасибо!

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

Delphin911 пишет:

старательно читал форум, но не хватило терпения. 

Туго у меня с английским

Или может ссылочку дайте, где об этом по русски почитать можно.

https://translate.google.ru/

Delphin911
Offline
Зарегистрирован: 25.12.2019

wdrakula пишет:

Delphin911 пишет:

старательно читал форум, но не хватило терпения. 

Туго у меня с английским

Или может ссылочку дайте, где об этом по русски почитать можно.

https://translate.google.ru/

Пользуюсь, когда надо перевести художественный текст. Тогда и посмеятся можно над переводом. А когда ты начинающий и многих терминов и т.п. нее знаешь - тяжело.

Т.е. вы хотите сказать, что в датащите это (что я мпрашиваю) описано и разъяснено? Хм. Попробую еще раз почитать. Помоему там черезчур все мудрено и без определенной подготовки не въедешь.

Вы хоть скажите, то что я написал правильно?

b707
Offline
Зарегистрирован: 26.05.2017

Delphin911 пишет:

Т.е. вы хотите сказать, что в датащите это (что я мпрашиваю) описано и разъяснено? Хм. Попробую еще раз почитать. Помоему там черезчур все мудрено и без определенной подготовки не въедешь.

абсолютно верно думаете.

Но только скажу вам, что "без определенной подготовки" оно и в переводе будет "черезчур все мудрено".

Так что путь один - набирать вот эту самую "подготовку", желательно одновременно с изучением английского

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

Delphin911 пишет:

Вы хоть скажите, то что я написал правильно?

1.Нет, почти всё неправильно.

2. Attiny13 безнадежно устаревшая вещь. Ровно с теми же "ножками" и той же ценой attiny85.

Delphin911
Offline
Зарегистрирован: 25.12.2019

wdrakula пишет:

1.Нет, почти всё неправильно.

2. Attiny13 безнадежно устаревшая вещь. Ровно с теми же "ножками" и той же ценой attiny85.

1. Инфу пот портам вроде из видео на ютуб каналах брал. Ну разве что по поводу PB5 сильно сомневался.

А что конкретно неправильно? Вот скажем, что PB0 и PB1 с поддержкой ШИМ это в Datasheet написано, уже нашел. И что порты с PB2 по PB5 аналоговые, тоже в Datasheet написано.

Table 21. Port B Pins Alternate Functions
Port Pin Alternate Function
PB5 RESET/dW/ADC0/PCINT5(1)
PB4 ADC2/PCINT4(2)
PB3 ADC3/CLKI/PCINT3(3)
PB2 SCK/ADC1/T0/PCINT2(4)
PB1 MISO/AIN1/OC0B/INT0/PCINT1/RXD(5)
PB0 MOSI/AIN0/OC0A/PCINT0/TXD(6)

Notes: 1. Reset pin, debugWire I/O, ADC Input channel, or Pin Change Interrupt.
2. ADC Input channel or Pin Change Interrupt.
3. ADC Input channel, Clock Input, or Pin Change Interrupt.
4. Serial Clock Input, Timer/Counter Clock Input, ADC Input Channel 0, or Pin Change
Interrupt.
5. Serial Data Input, Analog Comparator Negative Input, Output Compare and PWM
Output B for Timer/Counter, External Interrupt 0 or Pin Change Interrupt.
6. Serial Data Output, Analog Comparator Positive Input, Output Compare and PWM
Output A for Timer/Counter, or Pin Change Interrupt.

По поводу устарела - не буду спорить. Наверное. Просто у меня она есть сейчас и я эксперементирую на ней. Выводы вроде там одинаковые. Ну памяти в 85 8кб. А выводы суда по картинке такие же и так же в Datasheet без пол литры не разберешся сразу.

Ну а опыта как-то надо набираться!? Я вот еще с пол года назад, пока Ардуинкой не занялся, вообще ничего о микропроцессорах не знал.

Delphin911
Offline
Зарегистрирован: 25.12.2019

Вот еще нашел видео с простым и подробным описанием. https://www.youtube.com/watch?v=ibhgMzKOiJQ

Получается ошибался я только с 1 ногой, на которой только сброс.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Delphin911 пишет:

wdrakula пишет:

Delphin911 пишет:

старательно читал форум, но не хватило терпения. 

Туго у меня с английским

Или может ссылочку дайте, где об этом по русски почитать можно.

https://translate.google.ru/

Пользуюсь, когда надо перевести художественный текст. Тогда и посмеятся можно над переводом. А когда ты начинающий и многих терминов и т.п. нее знаешь - тяжело.

Т.е. вы хотите сказать, что в датащите это (что я мпрашиваю) описано и разъяснено? Хм. Попробую еще раз почитать. Помоему там черезчур все мудрено и без определенной подготовки не въедешь.

Вы хоть скажите, то что я написал правильно?

да нормально для автомата - запрос на член 'положить' в 'MyBuffer',  )))

Delphin911
Offline
Зарегистрирован: 25.12.2019

В общем понятно. Без диплома о знании программирования на низком уровне сюда обращаться не стоит. Засмеют.
А у меня в принципе все правильно. Я уже прошил свою первую тиньку.

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

Я объясню, почему была такая реакция на твои посты.

Delphin911 пишет:

Одни и те же выводы у нее могут быть и цифровыми и аналоговыми?

Да, конечно. Это совсем детский вопрос. После такого вопроса складывается мнение о несерьёзности интереса новичка.Такие обычно кинут пару дурацких вопросов и исчезают. Думай, как выглядишь.

Delphin911 пишет:

Судя по распиновке в даташите получается, что выводы PB5, PB2, PB4 и PB3 это аналоговые A0, A1, A2 и A3 соответственно(ADCX)? Ну т.е. в скетче мы их указываем как A0, A1, A2 и A3. А выводы PB0, PB1, PB2, PB3, PB4 и PB5 соответственно цифровые порты 0, 1, 2, 3, 4 и 5(PCINTX). При этом PB0 и PB1 поддерживают ШИМ (AINX). Или я не до конца понял распиновку?

Обозначения зависят от выбранного ядра, их более чем одно.  PCINTx  сокращение для Pin Change Interrupt - прерывания изменения состояния пина, то есть ты понял, что вообще из другой оперы? AIN0 и AIN1  входы аналогового компаратора. К ШИМу никакого отношения.

Delphin911 пишет:

Так же не до конца понял обозначения dW, CLKI, T0, INTX. Хотя dW, как и SCK, MISO, MOSI используются при программировании через Ардуино (возможно и не только).

Каша в голове. Не сочетается с тем, что ты прошил тиньку. Основное описание тиньки - около 100 страниц на примитивном "школьном" аглицком. Что там непонятно?

Delphin911 пишет:

Ну RESET вроде понятно, но тоже не разобрался каким уровнем сброс осуществляется. Туго у меня с английским, а Datasheet на нем родимом.

Черта над словом RESET на схеме как бы намекает на активный низкий, нет?

Ну вот мы и добрались до основы: новичок признается, что не читает по аглицки. Что показывает полную несерьёзность интереса. Электроникой и программированием без аглицкого заниматься нельзя. Совсем нельзя. Без дискуссий и обсуждений этого факта.

=======================

Поэтому и отношение, как ты выразился: "через губу". Может ты окажешься счастливым исключением из правила?

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

Простенький термометр для дистиллятора (еще не доделал термостойкую коробочку), скетч отсюда:

http://arduino.ru/forum/programmirovanie/attiny13a-101-primenenie?page=32#comment-446373

добавил изменение времени отправки данных в зависимости от температуры

#include <util/delay.h>     /* for _delay_us() */
#define periodusec 400 // mcs
#include <avr/sleep.h>
#include <avr/wdt.h>
#include <OneWire.h>

#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif

#define errTemp 1371

#define ds_pin PB4
OneWire ds18b20(ds_pin);

#define en_pin PB0

#define rf_pin PB3
#define RC_BIT rf_pin

#define defaultTimerCountSec 1812 // 30 min // 1027 = ~17min delay start by sec
word TimerCountSec = 10;
word CurrentTime = 0;

#define minTempControl 2300 //  = 30 'C
#define maxTempControl 3240 //  = 124 'C
#define minTimerSend 30 // = 30 sec
#define maxTimerSend 300 // = 5 min

void setup () {
  ExecFunc();
}

void loop () {
  CalcTimer();
  toSleep();
}

void ExecFunc() {
  word currT = getTemp();
  if (currT != errTemp) {
    if ((currT >= minTempControl) and (currT <= maxTempControl)) {
      TimerCountSec = map(currT, minTempControl, maxTempControl, minTimerSend, maxTimerSend);
      TimerCountSec = maxTimerSend - (TimerCountSec - minTimerSend);
    } else {
      TimerCountSec = defaultTimerCountSec;
    }
    currT += 21500;
    pinMode(en_pin, OUTPUT); digitalWrite(en_pin, HIGH); // RF ON
    pinMode(rf_pin, OUTPUT); digitalWrite(rf_pin, LOW); // OFF data RF
    sendRC(currT);
  } else {
    TimerCountSec = defaultTimerCountSec;
  }
  offPins();
}

void CalcTimer() {
  ++CurrentTime;
  if (((CurrentTime + 1) * 8) >= TimerCountSec) {
    CurrentTime = 0;
    ExecFunc();
  }
}

word getTemp() {
  byte dsData[9];
  ds18b20.reset();
  ds18b20.write(0xCC);
  ds18b20.write(0x44);
  delay(800);
  ds18b20.reset();
  ds18b20.write(0xCC);
  ds18b20.write(0xBE);
  for (byte i = 0; i < 9; i++) dsData[i] = ds18b20.read();
  if (OneWire::crc8(dsData, 8) != dsData[8]) return errTemp;
  word outTemp = (word)(dsData[1] << 8) + dsData[0];
  if ((word)(outTemp & 0x8000) == (word)(0x8000)) { // minus temp
    outTemp = (~outTemp) + (word)1;
    outTemp = (((word)6 * outTemp) + outTemp / (word)4) / (word)10;
  } else { // plus temp
    outTemp = (((word)6 * outTemp) + outTemp / (word)4) / (word)10;
    if (outTemp == 0) return errTemp;
    outTemp  += (word)2000;
  }
  return outTemp;
}

void offPins() {
  ds18b20.reset();
  digitalWrite(PB0, LOW); pinMode(PB0, INPUT);
  digitalWrite(PB1, LOW); pinMode(PB1, INPUT);
  digitalWrite(PB2, LOW); pinMode(PB2, INPUT);
  digitalWrite(PB3, LOW); pinMode(PB3, INPUT);
  digitalWrite(PB4, LOW); pinMode(PB4, INPUT);
}

ISR (WDT_vect)
{
  wdt_disable();  // disable watchdog
}

void toSleep() {
  cbi(ADCSRA, ADEN); // switch Analog to Digitalconverter OFF
  setup_watchdog(9);
  wdt_reset();  // pat the dog
  set_sleep_mode (SLEEP_MODE_PWR_DOWN);
  noInterrupts (); // timed sequence follows
  sleep_enable();
  sleep_bod_disable();
  interrupts ();  // guarantees next instruction executed
  sleep_cpu ();  // cancel sleep as a precaution
  sleep_disable();
}

// 0=16ms, 1=32ms,2=64ms,3=128ms,4=250ms,5=500ms
// 6=1 sec,7=2 sec, 8=4 sec, 9= 8sec
void setup_watchdog(int ii) {
  byte bb; int ww;
  if (ii > 9 ) ii = 9;
  bb = ii & 7;
  if (ii > 7) bb |= (1 << 5);
  bb |= (1 << WDCE); ww = bb;
  MCUSR &= ~(1 << WDRF);
  // start timed sequence
  WDTCR |= (1 << WDCE) | (1 << WDE);
  // set new watchdog timeout value
  WDTCR = bb; WDTCR |= _BV(WDIE);
}

void sendRC(unsigned long data) { // Отправка данных по радиоканалу RCswitch. Двоичный протокол
  DDRB |= _BV(RC_BIT);
  data |= 3L << 20; // ?
  unsigned short repeats = 1 << (((unsigned long)data >> 20) & 7);
  data = data & 0xfffff;
  unsigned long dataBase4 = 0; uint8_t i;
  for (i = 0; i < 20; i++) {
    dataBase4 <<= 1;
    dataBase4 |= (data % 2);
    data /= 2;
  }
  unsigned short int j;
  for (j = 0; j < repeats; j++) {
    data = dataBase4; uint8_t i;
    for (i = 0; i < 20; i++) {
      switch (data & 1) {
        case 0:
          PORTB |= _BV(RC_BIT);
          _delay_us(periodusec);
          PORTB &= ~_BV(RC_BIT);
          _delay_us(periodusec * 3);
          break;
        case 1:
          PORTB |= _BV(RC_BIT);
          _delay_us(periodusec * 3);
          PORTB &= ~_BV(RC_BIT);
          _delay_us(periodusec);
          break;
      }
      data >>= 1;
    }
    PORTB |= _BV(RC_BIT);
    _delay_us(periodusec);
    PORTB &= ~_BV(RC_BIT);
    _delay_us(periodusec * 31);
  }
}

- приемник

#include <RCSwitch.h>

RCSwitch mySwitch = RCSwitch();

#include <LiquidCrystal.h>
LiquidCrystal lcd(/*RS*/8,/*Enable*/9,/*DB4*/4,/*DB5*/5,/*DB6*/6,/*DB7*/7);

word lastCode = 0;
word lastTime = 0;
unsigned long timerSec = 0;
unsigned long current_millis;
unsigned long timerLigth;

void setup() {
  // put your setup code here, to run once:
  lcd.begin(16, 2);
  mySwitch.enableReceive(0);  // Receiver on inerrupt 0 => that is pin 2 // иницилизация.Используется вывод м/к с прерыванием под номером 0.
  pinMode(10, OUTPUT);
}

void loop() {
  current_millis = millis();
  // put your main code here, to run repeatedly:
  if ((millis() - timerSec) >= 1000UL) {
    timerSec = current_millis;
    ++lastTime;
    lcd.clear();
    lcd.print(lastTime);
    lcd.print(" sec ");
    word lts = lastTime / 60;
    lcd.print(lts);
    lcd.print(" min");
    lcd.setCursor(0, 1);
    unsigned long tmpcode = lastCode - 21500;
    lcd.print("  ");
    if (tmpcode >= 2000UL) {
      tmpcode -= 2000UL;
    } else {
      lcd.print("-");
    }
    lcd.print(tmpcode / 10);
    lcd.print(".");
    lcd.print(tmpcode % 10);
    lcd.print("  'C");
    /*lcd.print(lastCode);
      lcd.print("-->");
      lcd.print(tmpcode);*/
  }
  // receive street temp
  if (mySwitch.available()) {
    unsigned long receivedCode =  mySwitch.getReceivedValue();
    mySwitch.resetAvailable(); startLigth();
    lastTime = 0;
    lastCode = receivedCode;
  }
  // set display light
  if (analogRead(A0) < 500) startLigth();
  if ((current_millis - timerLigth) <= 5000UL) digitalWrite(10, HIGH); else digitalWrite(10, LOW);
  //--- end loop
}

void startLigth() {
  timerLigth = current_millis;
}

-

 

pittyalex
Offline
Зарегистрирован: 09.11.2016

Молодец. Ну или как далеко ловит? На сколько батарейки хватает?

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

pittyalex пишет:
Молодец. Ну или как далеко ловит? На сколько батарейки хватает?

Пробовал в пределах кухни, больше и не надо.
Потребление в спящем режиме 300 мкА, по примерным расчётам должно хватить на минимум 10 полноценных 6и часовых выгонов.

Green
Offline
Зарегистрирован: 01.10.2015

2032 на пределе по току, не? Я бы 3,6 акк поставил или даже АА/А.

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

Green пишет:

2032 на пределе по току, не?

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

Technoid91
Technoid91 аватар
Offline
Зарегистрирован: 20.05.2016

Delphin911 пишет:

Вот еще нашел видео с простым и подробным описанием.

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

Antarius
Offline
Зарегистрирован: 08.02.2017

Здравствуйте.

Попалась ATtiny13A, подскажите пример кода для датчика температуры DS18B20, чтобы он в нее влез.

В этой теме искал, но что-то не работает. Использую https://github.com/MCUdude/MicroCore это ядро.

Спасибо.

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

и в гугле нет? да ладно.....

и на этой ветке было страниц Х назад....

// OneWire функции:

void OneWireReset()
{
  PORTB &= ~_BV(DS_BIT);
  DDRB |= _BV(DS_BIT);
  _delay_us(500);
  DDRB &= ~_BV(DS_BIT);
  _delay_us(500);
}

void OneWireOutByte(uint8_t d)
{
  uint8_t n;
  for (n = 8; n != 0; n--)
  {
    if ((d & 0x01) == 1)
    {
      PORTB &= ~_BV(DS_BIT);
      DDRB |= _BV(DS_BIT);
      _delay_us(5);
      DDRB &= ~_BV(DS_BIT);
      _delay_us(60);
    }
    else
    {
      PORTB &= ~_BV(DS_BIT);
      DDRB |= _BV(DS_BIT);
      _delay_us(60);
      DDRB &= ~_BV(DS_BIT);
    }
    d = d >> 1;
  }
}


uint8_t OneWireInByte()
{
  uint8_t d, n, b;
  for (n = 0; n < 8; n++)
  {
    PORTB &= ~_BV(DS_BIT);
    DDRB |= _BV(DS_BIT);
    _delay_us(5);
    DDRB &= ~_BV(DS_BIT);
    _delay_us(5);
    b = ((PINB & _BV(DS_BIT)) != 0);
    _delay_us(50);
    d = (d >> 1) | (b << 7);
  }
  return (d);
}


word GetTemp() {
  uint8_t DSdata[2];
  OneWireReset();
  OneWireOutByte(0xcc);
  OneWireOutByte(0x44);
  PORTB |= _BV(DS_BIT);
  DDRB |= _BV(DS_BIT);
  unsigned long delp = millis(); while ((millis() - delp) <= 1000);
  //_delay_ms(1000); // если хотим ждать когда датчик посчитает температуру.
  DDRB &= ~_BV(DS_BIT);
  PORTB &= ~_BV(DS_BIT);
  OneWireReset();
  OneWireOutByte(0xcc);
  OneWireOutByte(0xbe);
  DSdata[0] = OneWireInByte();
  DSdata[1] = OneWireInByte();
  word TReading = (word)(DSdata[1] << 8) + DSdata[0];
  if ((word)(TReading & 0x8000) == (word)(0x8000)) {
    TReading = (~TReading) + (word)1;
    TReading = (((word)6 * TReading) + TReading / (word)4) / (word)10;
  } else {
    TReading = (((word)6 * TReading) + TReading / (word)4) / (word)10 + (word)2000;
  }
  return TReading;
}

брал пару лет назад на каком то буржуйском форуме, выше в ветке где то даже ссылка на исходник была, на attiny85 точно работает, на 13ой тоже должно.

Antarius
Offline
Зарегистрирован: 08.02.2017

Спасибо большое!

Этот код я видел, отдельно он комилируется без ошибок

 

У меня проектик такой - attiny13a + жк дисплей (б/у от промышленного автоматического выключателя, их много есть у меня) на контроллере pcf2111T и датчик температуры ds18b20.

Все это на батарейке красиво должно висеть на стене, и показывать температурку.

Я написал код для контроллера диспля, он работает, показывает любое число на экранчике.

Отдельно компилируется Ваш код. 

Но вместе они вызывают странную ошибку:

error: can't find a register in class 'POINTER_REGS' while reloading 'asm'
 
   asm volatile ("rcall _millis" : "=w" (m) :: "r30");
 
error: 'asm' operand has impossible constraints
 
Потому ищу какой-нибудь еще код, сам написать не могу, ума не хватает.
andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

Antarius пишет:

это на батарейке красиво должно висеть на стене, и показывать температурку.

батарейка будет размером больше чем устройство :(

 

Antarius
Offline
Зарегистрирован: 08.02.2017

Почему? PCF жрет сотни микроампер, аттини тоже не очень много.

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

Antarius пишет:

сотни микроампер

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

Antarius
Offline
Зарегистрирован: 08.02.2017

andycat пишет:

вот и посчитайте

 

Аттинька 700мкА на 1Мгц при 3Вольтах питания + контроллер с экраном ну пусть 150 мкА + ну чего-нибудь еще до кучи. Пусть будет 1мА в час. Если запитать от трех батареек АА, через повышающе/понижающий DC-DC, который высосет батарейки в нуль, ну допустим 3000мА, то хватит на 3000 часов или на 4 месяца.И это при непрерывной работе, а если использовать сон для аттиньки? У контроллера тоже есть режимы заморозки изображения и засыпания. Я надеюсь, на полгода минимум, а то и годик :)

Antarius
Offline
Зарегистрирован: 08.02.2017

Подскажите пожалуйста еще по вашему примеру, если возможно.

В конце описана функция getTemp(), выдающая в ответ на ее вызов переменную типа word (return TReading;)

Далее я переменную с результатом функции getTemp() раскладываю в другой своей функции на цифры типа byte для экранчика по разрядам, и на этом у меня заканчивается память и ее очень сильно не хватает. Можете подсказать как бы получить температуру не в виде такой жирной переменной, а в виде чего-то более компактного, лучше трех цифирок типа byte например + 25,4 было бы просто 2 5 4? Я же комнатную температуру измеряю, тут отрицательных или слишком больших температур не ожидается.

 

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

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

b707
Offline
Зарегистрирован: 26.05.2017

Antarius пишет:

Аттинька 700мкА на 1Мгц при 3Вольтах питания + контроллер с экраном ну пусть 150 мкА

если у вас тинька 700 мкА жрет - что-то я сильно сомневаюсь. что экран всего 150...

Yurchik26
Offline
Зарегистрирован: 16.03.2013

Самая примитивная подмотка спидометра. Основана на millis. Точность вообще не нужна, настраивается на глаз. Регулирует период по отрицательному и положительному полупериоду. Может кому пригодится

#include <EEPROM2.h>
int result1 = 1000;
int result2 = 1000;
byte flag1 = 0;
byte flag2 = 0;
byte flag3 = 0;
boolean menu = false;
boolean flag = false;

long timer = 0, timerPrev1 = 0, timerPrev2 = 0;

void(* resetFunc) (void) = 0;

void setup() {
  result1 = int(EEPROM.read(20));
  result2 = int(EEPROM.read(25));
  DDRB |= (1 << 4); //  pinMode(relay, OUTPUT);
  PORTB &= ~(1 << 4); //  digitalWrite(relay, LOW);
  DDRB &= ~(1 << 0); //  pinMode(button1, INPUT);
  DDRB &= ~(1 << 1); //  pinMode(button2, INPUT);
  DDRB &= ~(1 << 2); //  pinMode(button3, INPUT);
  delay(3000);
}


void loop() {
  timer = millis();
  result1 = constrain(result1, 1, 1000);
  result2 = constrain(result2, 1, 1000);
  if (timer >= 100000001)resetFunc();
  if (timer - timerPrev1 > result1 && flag == false) {
    PORTB |= (1 << 4);
    flag = true;
    timerPrev2 = timer;
  }
  if (timer - timerPrev2 > result2 && flag == true) {
    PORTB &= ~(1 << 4);
    flag = false;
    timerPrev1 = timer;
  }
  if (!(PINB & (1 << PINB0)) && flag1 == 0) { // обработчик первой кнопки вверх
    if (menu == true) result1 += 10;
    if (menu == false) result2 += 10;
    flag1 = 1;
  }
  if (PINB & (1 << PINB0) && flag1 == 1) flag1 = 0;
  if (!(PINB & (1 << PINB1)) && flag2 == 0) { // обработчик второй кнопки вниз
    if (menu == true) result1 -= 10;
    if (menu == false) result2 -= 10;
    flag2 = 1;
  }
  if (PINB & (1 << PINB1) && flag2 == 1) flag2 = 0;
  if (!(PINB & (1 << PINB2)) && flag3 == 0) { // обработчик третей кнопки меню
    EEPROM.write(20, result1);
    EEPROM.write(25, result2);
    delay(5);
    menu = !menu;
    flag3 = 1;
  }
  if (PINB & (1 << PINB2) && flag3 == 1) flag3 = 0;
}

 

Yurchik26
Offline
Зарегистрирован: 16.03.2013

Программируемый таймер, с настройкой через одну кнопку, с выводом на один светодиод на какое время запрограммирован (мигает светодиодом как сигнализация на машинах при программировании). Делалось для продувки котла на теплицу. Прошу язвительные комментарии типо (такой скетч в топку) не писать, или пишите, но тогда и пишите сразу по делу что где поменять, и что как сделать лучше. Оба скетча написаны для Attiny 13 ( по размеру влазят и работают)

#include <EEPROM2.h>
byte result;
byte flag = 0;
byte tens = 0;
byte ones = 0;

long timer = 0, timerPrev = 0, ms1 = 0;

void(* resetFunc) (void) = 0;

void setup() {
  result = int(EEPROM.read(20));
  DDRB |= (1 << 1); //  pinMode(ledPin, OUTPUT);
  DDRB |= (1 << 0); //  pinMode(relay, OUTPUT);
  DDRB &= ~(1 << 2); //  pinMode(button, INPUT);
  PORTB &= ~(1 << 1); //  digitalWrite(ledPin, LOW);
  PORTB &= ~(1 << 0); //  digitalWrite(relay, LOW);
  delay(3000);
}

void loop() {
  timer = millis();
  if (timer >= 1000000001) resetFunc();
  if (timer - timerPrev > 60000 * result) {
    PORTB |= (1 << 0);
    delay(1900);
    PORTB &= ~(1 << 0);
    timerPrev = timer;
  }
  PORTB |= (1 << 2);
  if (!(PINB & (1 << PINB2)) && flag == 0) {
    if (result > 59)result = 0;
    result++;
    EEPROM.write(20, result);
    delay(5);
    flag = 1;
  }
  if (PINB & (1 << PINB2) && flag == 1) flag = 0;
  if (tens == 0 && ones == 0) {
    ms1 = ms1 + 1500;
    tens = result / 10;
    ones = result - (tens * 10);
  }

  if (tens > 0) {
    if ( ( timer - ms1 ) > 700) ms1 = timer;
    if (!(PINB & (1 << PINB1))) PORTB |= (1 << 1);
    else {
      PORTB &= ~(1 << 1);
      tens--;
    }
  }
}
else if  (ones > 0) {
  if ( ( timer - ms1 ) > 300) ms1 = timer;
  if (!(PINB & (1 << PINB1))) PORTB |= (1 << 1);
  else {
    PORTB &= ~(1 << 1);
    ones--;
  }
}
}
}

 

ujin
Offline
Зарегистрирован: 06.09.2016

Delphin911  в сети есть даташит на атмегу 128 на русском, гугл его знает, почти  все в нем сайдет для тиньки...остальное так же гугл поможет ).

DisSevsk
Offline
Зарегистрирован: 02.09.2020

Всем привет, только начинаю осваивать тему с микроконтрллерами и в частности с аттини13, так вот возник вопрос по части: у тиньки мало пинов для работы, хотелось бы еще задействовать RESET, как я понял он настраивается фьюзом RSTDISBL, после этого контроллер невозможно будет прошить обычным SPI-программатором. В даташите написано, что для прошивки на этот пин нужно будет подать напряжение +12в. Так вот: достаточно ли будет просто подключить +12в на ресет и прошить стандартным USBSPI программатором?

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

DisSevsk пишет:

достаточно ли будет просто подключить +12в на ресет и прошить стандартным USBSPI программатором?

Нет. Схема, канеш, ужасная там, но вот 

https://habr.com/ru/post/249967/

dimaris
dimaris аватар
Offline
Зарегистрирован: 27.03.2012

Однажды тоже тестировал прошивки на ATtiny13 с использованием резетовой ноги, спаял себе доктора, работает отлично!

http://www.getchip.net/posts/059-ispravlyaem-avr-fyuzy-pri-pomoshhi-atme...

Honey
Offline
Зарегистрирован: 01.10.2020

Пополню ряды любителей ATTiny13A) Мой проект "1-wire счетчик импульсов" (программная реализация DS2423) тоже работает на ATTyny13A

b707
Offline
Зарегистрирован: 26.05.2017

Honey пишет:

Пополню ряды любителей ATTiny13A) Мой проект "1-wire счетчик импульсов" (программная реализация DS2423) тоже работает на ATTyny13A

вброс засчитан.

Чтобы это было нормальным сообщением. нужно добавить схему и код

Honey
Offline
Зарегистрирован: 01.10.2020

b707 пишет:

Honey пишет:

Пополню ряды любителей ATTiny13A) Мой проект "1-wire счетчик импульсов" (программная реализация DS2423) тоже работает на ATTyny13A

вброс засчитан.

Чтобы это было нормальным сообщением. нужно добавить схему и код

У этого МК 1024 байта памяти программ. Те, кто программирует под него более-менее сложные вещи, понимают, что это можно сравнить с искусством. Я лишь хотел сказать, что я тоже "в клубе" любителей этого МК.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Honey пишет:

b707 пишет:

Honey пишет:

Пополню ряды любителей ATTiny13A) Мой проект "1-wire счетчик импульсов" (программная реализация DS2423) тоже работает на ATTyny13A

вброс засчитан.

Чтобы это было нормальным сообщением. нужно добавить схему и код

У этого МК 1024 байта памяти программ. Те, кто программирует под него более-менее сложные вещи, понимают, что это можно сравнить с искусством. Я лишь хотел сказать, что я тоже "в клубе" любителей этого МК.

 какое такое искуство? на PIC16F84 я делал контроллер управления вязальной машиной, там было более 10 программ пользователя, для управления двигателем переменного тока -программный детектор нуля, тормоз, реверс и т.д. памяти еще оставалось немного

Honey
Offline
Зарегистрирован: 01.10.2020

ua6em пишет:

 какое такое искуство? на PIC16F84 я делал контроллер управления вязальной машиной, там было более 10 программ пользователя, для управления двигателем переменного тока -программный детектор нуля, тормоз, реверс и т.д. памяти еще оставалось немного

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

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

в 1024 байта еще и порнуху можно впихнуть !

Honey
Offline
Зарегистрирован: 01.10.2020

Komandir пишет:

в 1024 байта еще и порнуху можно впихнуть !

Во-во, ascii-art называется, есть и такое искусство)

b707
Offline
Зарегистрирован: 26.05.2017

Honey пишет:

У этого МК 1024 байта памяти программ. Те, кто программирует под него более-менее сложные вещи, понимают, что это можно сравнить с искусством. Я лишь хотел сказать, что я тоже "в клубе" любителей этого МК.

и что? Смысл вашего поста в чем - прокричать "я тоже могу 20 раз", как в том анекдоте? :)

Я и говорю "вброс"

Игорь Я
Offline
Зарегистрирован: 03.09.2018

Доброго дня (вечера) Всем!

Я тут появлялся года 2 назад с темой программирования Attiny13, спасибо помогли. 

Теперь новая загвоздка: на тини13 реализовать схему цикличного таймера на 24 часа.  На выводе Pin3 через сутки меняется уровень с 0 на 1 (уход +- 10 минут за сутки допускается). На выводе Pin4 уровень меняется с частотой 0,5Гц - для светодиода.

Код зашил в аттини. На малых режимах времени работает нормально, но при установке 12 часов переключение происходит с запаздыванием почти на 40-50 минут в течение суток. Я представляю какой будет разброс если введу 24 часа...

Местные Гуру, помогите советом!

вот прога

 
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
// Эти переменные хранят временной шаблон для интервалов мигания
// и текущее состояние светодиодов
 
int ledPin1 = 3; // номер пина со светодиодом
int ledState1 = LOW; // состояние светодиода
// последний момент времени, когда состояние светодиода изменялось
unsigned long previousMillis1 = 0;
long OnTime1 = 42408000; // длительность свечения светодиода (в миллисекундах)
long OffTime1 = 42408000; // светодиод не горит (в миллисекундах)
 
int ledPin2 = 4; // номер пина со светодиодом
int ledState2 = LOW; // состояние светодиода
// последний момент времени, когда состояние светодиода изменялось
unsigned long previousMillis2 = 0;
long OnTime2 = 500; // длительность свечения светодиода (в миллисекундах)
long OffTime2 = 500; // светодиод не горит (в миллисекундах)
 
void setup() {
// устанавливаем цифровой пин со светодиодом как ВЫХОД
pinMode(ledPin1, OUTPUT);
pinMode(ledPin2, OUTPUT);
}
 
void loop() {
// выясняем не настал ли момент сменить состояние светодиода
 
unsigned long currentMillis = millis(); // текущее время в миллисекундах
 
// конечный автомат для 1-го светодиода
if((ledState1 == HIGH) && (currentMillis - previousMillis1 >= OnTime1))
{
   ledState1 = LOW; // выключаем
   previousMillis1 = currentMillis; // запоминаем момент времени
   digitalWrite(ledPin1, ledState1); // реализуем новое состояние
}
else if ((ledState1 == LOW) && (currentMillis - previousMillis1 >= OffTime1))
{
   ledState1 = HIGH; // выключаем
   previousMillis1 = currentMillis ; // запоминаем момент времени
   digitalWrite(ledPin1, ledState1); // реализуем новое состояние
}
 
// конечный автомат для 2-го светодиода
if((ledState2 == HIGH) && (currentMillis - previousMillis2 >= OnTime2))
{
   ledState2 = LOW; // выключаем
   previousMillis2 = currentMillis; // запоминаем момент времени
   digitalWrite(ledPin2, ledState2); // реализуем новое состояние
}
else if ((ledState2 == LOW) && (currentMillis - previousMillis2 >= OffTime2))
{
   ledState2 = HIGH; // выключаем
   previousMillis2 = currentMillis ; // запоминаем момент времени
   digitalWrite(ledPin2, ledState2); // реализуем новое состояние
}
}

 

nik182
Offline
Зарегистрирован: 04.05.2015

Прочитайте что нибудь про внутренний генератор. Например http://www.gaw.ru/html.cgi/txt/app/micros/avr/AVR053.htm
Его можно подстраивать и получить нужную Вам точность. А вообще всё это описано в мануале на процессор. Опять стандартный отсыл - почитать мануал перед тем как задавать вопрос или вообще перед работой с процессором. Что мешает это сделать?

Игорь Я
Offline
Зарегистрирован: 03.09.2018

Частоту-то я подстрою, только похоже подстройку я делал при питании от 5 вольт, а сейчас запитал от 3.6 вольта, может по этому и сбился внутренний генератор?

 

 

nik182
Offline
Зарегистрирован: 04.05.2015

Да. Частота зависит от питания. В мануле есть график зависимости от питания. Можно измерять напряжение питания и подстраивать генератор. И также от температуры - измерять и подстраивать. Можно получить хороший результат. 

Joiner
Offline
Зарегистрирован: 04.09.2014

А часы реального времени не спасут? В самом простом случае можно с них считать секундные импульсы. Мои часики идут уже более 3-х лет, ни разу их не подправлял. За это время ушли вперед меньше трех минут. Точность очень хорошая, а цена копеечная.

Или кварц поставить.... Тоже вариант

Green
Offline
Зарегистрирован: 01.10.2015

Кварц не спасёт. Если только внешний генератор. Калибровка внутреннего наиболее простое решение для 10 мин расхождения за сутки.

Joiner
Offline
Зарегистрирован: 04.09.2014

Green пишет:

.................................... Калибровка внутреннего наиболее простое решение для 10 мин расхождения за сутки.

10 мин за сутки, и менее трех минут за три года. Между ними пропасть!

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

питание 5 вольт, в термостат и нагреть до 75 градусов, и завести свой таймер минут с корректировкой к примеру каждые 5 минут, на выбег за эти 5 минут

Green
Offline
Зарегистрирован: 01.10.2015

Joiner пишет:
10 мин за сутки, и менее трех минут за три года. Между ними пропасть!


3х минут небыло, не сочиняйте.)

Joiner
Offline
Зарегистрирован: 04.09.2014

Можно купить такой модуль https://aliexpress.ru/item/32317422637.html , или отдельную микросхемку DC3231 и попробовать ее в деле. Точность фантастическая. Если не нужно считывать реальное время, дату, день недели, то можно просто использовать как точнейший генератор секундных импульсов. Попробуй, уверен, что точность удивит.