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

ПавеJI
Offline
Зарегистрирован: 01.05.2018

СПС

Антон142
Offline
Зарегистрирован: 21.01.2016

Подскажите схему/код "ограничителя нарпяжения"  на уровне 3.5в,  на Attiny13 для фонарика питание от Li-ion.

int i = 126;
void setup() {
  analogReference(INTERNAL);
  pinMode(0, OUTPUT); // Задаем напругу
  pinMode(A2, INPUT); //Замеряем напругу
}
void loop() {
  analogWrite(0, i);
  if  (analogRead(A2) < 500 ) { //Если напряжение меньше заданного, уменьшаем скважность ШИМ
    i = i - 1;
  }
  if  (analogRead(A2) > 500 ) {//Если напряжение больше заданного, увеличиваем скважность ШИМ
    i = i + 1;
  }
}

В результате выдает 2,5 вольт и никак не реагирует на задание analogRead(A2) 

trembo
trembo аватар
Offline
Зарегистрирован: 08.04.2011

У вас переменное напряжение,
а вы его измеряете как будто оно постоянное .
Попробуйте кондёрчик 10 нан параллельно нижнему резистору.

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

Да вы посмотрите, какие там номиналы резисторов. Ваши 10 Нан там ничего не сделают. Резисторы у увеличить в 1000 раз. Тогда и кондёр может поможет.
И знаки сравнения мне кажется надо поменять на инверсные.

trembo
trembo аватар
Offline
Зарегистрирован: 08.04.2011

pittyalex пишет:
Да вы посмотрите, какие там номиналы резисторов. Ваши 10 Нан там ничего не сделают. Резисторы у увеличить в 1000 раз. Тогда и кондёр может поможет. И знаки сравнения мне кажется надо поменять на инверсные.

Кондёры и резисторы слишком большие нельзя.
У вас будет такое большое время реакции что без балластного резистора  нафик выгорит светодиод.

Антон142
Offline
Зарегистрирован: 21.01.2016

Диод прекрасно напрямую работает от li ion не сгорает.транзистор p-channel поэтому такие знаки

Антон142
Offline
Зарегистрирован: 21.01.2016

Вот рабочая схема ограничителя напряжения, оказывает рабочее напряжение на светодиоде  2.95В, поэтому аккмулятор может высосать весь, защиты нет. 

 

byte i = 250;
void setup() {
  TCCR0B = 0x02;
  analogReference(INTERNAL);
  pinMode(0, OUTPUT); // Задаем напругу
  pinMode(A2, INPUT); //Замеряем напругу
}
void loop() {
  analogWrite(0, i);
  if  (analogRead(A2) < 430 ) //Если напряжение меньше заданного, уменьшаем скважность ШИМ
    i = max (i - 1, 0);
  if  (analogRead(A2) > 430 )  //Если напряжение больше заданного, увеличиваем скважность ШИМ
    i = i + 1;
  }

Ток зависит от длины проводов при настройке, конечно правильнее ограниивать ток  и ставить защиту на разряд акккмулятора,но мне пока лень. На схеме ресторы в кОм. 

СергейНСК
Offline
Зарегистрирован: 22.11.2014

Если вы сказали, что на диоде 2.95в, то через резисторы течет ток 195мА. Он не нужен в измерительной цепи. Увеличивайте в 1000 раз сопротивления. Вам уже писали выше.

Антон142
Offline
Зарегистрирован: 21.01.2016

Извиняюсь не заметил, резисторы конечно же в кОм.

slider
Offline
Зарегистрирован: 17.06.2014

ребят, пытаюсь вогнать attiny13a в сон, но вот почему после   

sleep_enable(); // разрешаем сон
sleep_cpu();    // спать!

attiny13a сразу же просыпается , в отличии от любой другой ардуины   

код пробовал от сюда http://arduino.ru/forum/programmirovanie/attiny13a-101-primenenie?page=11#comment-122090
но там она засыпает , потому как  бесконечно ее заново вводят  в сон 

while(1) {
51     sleep_enable(); // разрешаем сон
52     sleep_cpu(); // спать!
53   }

а так не засыпает: 

while(1) {
   
    sleep_cpu(); // спать!
    }

Вот какого фига она сама по себе, без постоянного втыка в сон, просыпается?

написал простой пример одноразового Blink

#include <avr/sleep.h>

#define LED 2

void setup()
 {
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  pinMode(LED, OUTPUT); 
}

void loop() 
{
  digitalWrite(LED, HIGH);   
  delay(1000);                     
  digitalWrite(LED, LOW);    
  delay(1000);                      

   sleep_enable(); // разрешаем сон
   sleep_cpu();    // спать!
  
}

здесь тинька13 мигает бесконечно , в отличии от других ардуин и дигиспарка аттини85. 
Что не так делаю при вводе ее в сон не пойму.

// arduinoIDE 1.8.5     , платы устанавливал и пробовал разные: MicroCore - attiny13 , attiny13 - attiny13(attiny13a) . Оболочки тоже  IDE 1.6.3  ,  1.5.8

//// планирую сделать просыпание по нажатию кнопки на PB0 (PCINT0) 

 

////// только если выключить все прерывания 

cli();
sleep_enable(); // разрешаем сон
sleep_cpu();    // спать!

тогда она норм. засыпает, значит какое-то прерывание ее пробуждает по умолчанию. Как его выборочно отрубить?
 

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

вспоминать как работает некогда, вот отсюда возьмите просыпание по кнопке - 100% работает.

http://arduino.ru/forum/proekty/miniatyurnyi-komnatnyi-termometr-na-attiny85-c-oled#comment-32533

к сожалению не уверен что на 13ой есть прерывание PCINT3 поэтому не уверен что заработает

slider
Offline
Зарегистрирован: 17.06.2014

благодарю. проверил.

повторюсь , сон работающий на attiny85, и др. ардуино, не работает на attiny13a , она сразу же от чего-то сама просыпается.

вот упростил ваш код (по логике раз вы используете PCINT3, то  вместо ISR(PCINT0_vect) {
 просится ISR(PCINT3_vect) { . но работает и так и так.

#include <avr/sleep.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

// PB0 pin 5 - SDA
#define PB0_OUT sbi(DDRB,PB0)
#define PB0_IN cbi(DDRB,PB0)
#define PB0_HIGH sbi(PORTB,PB0)
#define PB0_LOW cbi(PORTB,PB0)
// PB1 pin 6
#define PB1_OUT sbi(DDRB,PB1)
#define PB1_IN cbi(DDRB,PB1)
#define PB1_HIGH sbi(PORTB,PB1)
#define PB1_LOW cbi(PORTB,PB1)
// PB2 pin 7 - SCL
#define PB2_OUT sbi(DDRB,PB2)
#define PB2_IN cbi(DDRB,PB2)
#define PB2_HIGH sbi(PORTB,PB2)
#define PB2_LOW cbi(PORTB,PB2)
// PB3 pin 2 - WakeUp KEY
#define PB3_OUT sbi(DDRB,PB3)
#define PB3_IN cbi(DDRB,PB3)
#define PB3_HIGH sbi(PORTB,PB3)
#define PB3_LOW cbi(PORTB,PB3)
#define PB3_READ bitRead(PINB,PB3)
// PB4 pin 3
#define PB4_OUT sbi(DDRB,PB4)
#define PB4_IN cbi(DDRB,PB4)
#define PB4_HIGH sbi(PORTB,PB4)
#define PB4_LOW cbi(PORTB,PB4)


ISR(PCINT3_vect) {
  if (PB3_READ == 0) { // LOW level KEY
    sleep_disable();
    cbi(GIMSK, PCIE);
    cbi(PCMSK, PCINT3);
  }
}

void toSleep() {
// pins mode
  // PB0_IN; PB0_LOW;
  // PB1_OUT; PB1_LOW;
  //  PB2_IN; PB2_LOW;
  // PB3_IN; PB3_HIGH; // LOW = OFF res, if HIGH level KEY
  //  PB4_OUT; PB4_LOW;
// sleep
  cbi(ADCSRA, ADEN);
  set_sleep_mode (SLEEP_MODE_PWR_DOWN);
  sleep_enable();
  sbi(GIMSK, PCIE);
  sbi(PCMSK, PCINT3);
  sleep_mode();
}

void setup () {
  PB2_OUT; PB2_LOW; delay(1000); 
  PB3_IN;  PB3_HIGH;
}

void loop () {
PB2_HIGH;
delay(1000);
PB2_LOW;
delay(1000);
toSleep();

}

Attiny85 хорошо засыпает , и потребляет 0.45 мкА

Attiny13 сразу же просыпается.

при ее зацикливании (что не гоже для будующего кода):

while (1) {   
   sleep_enable(); // разрешаем сон
   sleep_cpu();    // спать!
 }

и равно

while (1) {   
         sleep_enable();
         sbi(GIMSK, PCIE);
         sbi(PCMSK, PCINT3);
         sleep_mode();
 }

и равно

while (1) {   
         sleep_enable();
         sleep_mode();
 }

она "засыпает" (от чего-то просыпается , выполняет строчки кода по вновь уходу в сон)
в итоге она потребляет 10..8мкА в якобы сне .

/// по вашему коду вопрос , вот она проснулась по отпусканию кнопки, попадает в прерывание и не выполняет условие 

157   if (PB3_READ == 0) { // LOW level KEY
158     sleep_disable();
159     cbi(GIMSK, PCIE);
160     cbi(PCMSK, PCINT3)

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

 

 

slider
Offline
Зарегистрирован: 17.06.2014

Жуть , 2дня потратил чтоб со сном тиньки разобраться . Поставил уже Atmel Studio , программатор USBASP .
два кода помогли из статеек (через Atmel Studio , потребление тока меньше)
http://www.count-zero.ru/2016/attiny13/   
https://blog.radiotech.kz/avr/rezhim-power-down-mikrokontrollerov-serii-tiny/

максимум чего удалось добиться , это снижение с 10мкА до 2мкА (0.1мкА) ( BOD выбран  Disable, в панели Инструменты , хотя не имеет значения )

путем замены конструкции

void setup() {
  // put your setup code here, to run once:

}

void loop() {
  // put your main code here, to run repeatedly:

}

на конструкцию из Atmel Studio


int main(void)  {
// то что выполняется 1 раз (настройки)


// главный цикл программы
 while(1) { 


}

}

Убивает сразу 2 зайца !!! 
1. не надо бесконечно заново усыплять тиньку. все работает с одного раза. 
2. значительно падает энергопотребление.

Второй косяк - это подвернулись как раз таки недо тиньки (видимо подделка) - снизу круг, в нем надписи.
ток у них падает с 10мкА до 2мкА.

У тинек , что снизу в три строчки надписи
ток у них падает с 8мкА до 0.1мкА , это  100наноАмпер !!! вот оно, кота за яй.. :)))  

минимальный проверочный кодик:

//// #include <avr/sleep.h>

//void setup () { }
//void loop () {

int main(void) {
// не влияет в глубоком сне:
/// PRR = (1<<PRTIM0) | (1<<PRADC); // shut down Timer0 & ADC
///  PRR = (1<<PRADC);                        // shut down ADC

DDRB=0x04;    // PB2 на выход
PORTB=0x04;  // PB2 лог1.
delay(1000);
PORTB=0x00; // PB2 лог0.
delay(1000);
 
 //// set_sleep_mode (SLEEP_MODE_PWR_DOWN);
 //// sleep_enable();
  MCUCR |= (1<<SM1); // power-down mode
  MCUCR &= ~(1<<SM0); // power-down mode
  MCUCR |= (1<<SE);

  // while(1) {
  //// sleep_cpu();
   asm("sleep");
  //  }

}

//  Полагаю  что это плохо собрано ядро Attiny13 для Arduino IDE , ведь с attiny85 digispark таких проблем нет, как и с другими ардуинками.

СергейНСК
Offline
Зарегистрирован: 22.11.2014

Может результат "замены конструкции" можно объяснить? Тем, что конструкция setup() автоматически включает всю периферию? А main(void) ничего не включает?

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

Почитайте, как работает delay() и millis(). Думаю вам все станет ясно.
А вот что за поддельные линьки, это интересно. Почитайте у них chipID. Сравните с другими. Вряд-ли будут китайцы разрабатывать новую архитектуру. Может производственный брак? Может что-то не отключили? И надо ещё errata на тини13 прочитать.

slider
Offline
Зарегистрирован: 17.06.2014

Слева проблемный:

верх-

 

низ-

Покупал на Али пару десяток у разных продавцов, один "левый" десяток attiny13а не видился программаторами. 
Помогло высоковольтное параллельное программирование. (HVPROG реаниматор не смог). А именно помогла восстанавливалка фьюзов на базе ARDUINO UNO (добавляется только транзюк для подачи 12в не резет контроллера ). Значит они все были с прошитым spien , естественно контроллеры ничем не видятся, никакой распространеный программотор невзял (ибо они все последовательного программирования).

восстанавал по статье https://habr.com/post/249967/  ( https://sites.google.com/site/wayneholder/attiny-fuse-reset ).  ID естественно у них одинаковы с оригинальными: Arduino IDE , и программаторы всякие после восстановления их хорошо видят и шьют.  

Фьюзы в верхних опытах у них уже одинаковы (восстанавливалкой по обоим прошелся) , тем более Arduino IDE при заливке скетча через Arduino as ISP , сама перешивает фьюзы в зависимости от настроек платы(частота,...) .

В инете инфа про поддельные attiny , atmega328 , atmega fake  редко, но встречаются. 
https://www.sparkfun.com/news/350    https://www.sparkfun.com/news/364    

https://www.avrfreaks.net/comment/1922186#comment-1922186

так-то гуглится fake avr , fake atmel , и коды-тесты попадались.

// Предполагаю  что встречаестя разный тех процесс, разные fuse по умолчанию. М.б. при сбросе контроллера периферия разная включается. на проверку домыслов нет времени.

//// по errata http://www.cyberforum.ru/avr/thread2084902.html , незнаю где именно он пишется на низе микросхемы . Согласно даташиту , ревизий четыре A B C D . На левых малазийских кодировка снизу вообще не та. Походу они свою несуществующую errata - E придумали :)

slider
Offline
Зарегистрирован: 17.06.2014

не восстанавливаются fuse avr attiny attiny13a (для гугла чтоб потом нашел)
и еще припомнилось , что фьюзы поначалу не хотели шиться , методом тыка пришел к тому что 

!!!!! помогло только с поправкой:

добавил 

writeFuse(LFUSE, 0xFF); 

writeFuse(HFUSE, 0xFF); 

перед

writeFuse(LFUSE, 0x6A); 

writeFuse(HFUSE, 0xFF);



Купил на ебае десяток ATTINY13A ни какими программаторами не видятся, ни какими fuse doctor не восстанавливаются (жаль много времени на это всё потратил). Добивал из принципа. Мне помогла ранняя разработка этой схемы на arduino, по случайности, по ошибке перепутал hfuse lfuse ff 6a, только после этого fuse поменялись, потом заменил значение как надо, и о чудо! fuse встали как надо. Теперь переделал на эту программу (что и указал выше). Теперь тиньки видятся всеми программаторами. Предполагаю, что китайцы использовали другой тип памяти для fuse, и чтобы его переписать, его сначала надо затереть в FF.  Видимо мне попались совсем корявые значения  у косячных LFuse: 79, HFuse: F8 (никак не хотели меняться на правильные) после замены на LFuse: FF, HFuse: FF, затем уже на 6A, FF встали правильные LFuse: 6A, HFuse: FF 

УРА!!! ВОССТАНОВЛЕНИЕ FUSE ATTINY13A!

комент черкнул здесь:  ATTINY13A с завода - обычный ISP вам не поможет

 http://we.easyelectronics.ru/digitdroid/attiny13a-s-zavoda---obychnyy-isp-vam-ne-pomozhet.html

Подправленный скетч Fuse_reanimator.ino : (ожидание ввода символа с клавы для начала восстановления в нем закоментил , чтоб без компа можно было сразу после подачи питания восстановить, delay(5000) - автоповтор повтор каждые 5сек ) 

// AVR High-voltage Serial Fuse Reprogrammer
// Adapted from code and design by Paul Willoughby 03/20/2010
//   http://www.rickety.us/2010/03/arduino-avr-high-voltage-serial-programmer/
//
// Fuse Calc:
//   http://www.engbedded.com/fusecalc/

#define  RST     13    // Output to level shifter for !RESET from transistor
#define  SCI     12    // Target Clock Input
#define  SDO     11    // Target Data Output
#define  SII     10    // Target Instruction Input
#define  SDI      9    // Target Data Input
#define  VCC      8    // Target VCC

#define  HFUSE  0x747C
#define  LFUSE  0x646C
#define  EFUSE  0x666E

// Define ATTiny series signatures
#define  ATTINY13   0x9007  // L: 0x6A, H: 0xFF             8 pin
#define  ATTINY24   0x910B  // L: 0x62, H: 0xDF, E: 0xFF   14 pin
#define  ATTINY25   0x9108  // L: 0x62, H: 0xDF, E: 0xFF    8 pin
#define  ATTINY44   0x9207  // L: 0x62, H: 0xDF, E: 0xFFF  14 pin
#define  ATTINY45   0x9206  // L: 0x62, H: 0xDF, E: 0xFF    8 pin
#define  ATTINY84   0x930C  // L: 0x62, H: 0xDF, E: 0xFFF  14 pin
#define  ATTINY85   0x930B  // L: 0x62, H: 0xDF, E: 0xFF    8 pin

void setup() {
  pinMode(VCC, OUTPUT);
  pinMode(RST, OUTPUT);
  pinMode(SDI, OUTPUT);
  pinMode(SII, OUTPUT);
  pinMode(SCI, OUTPUT);
  pinMode(SDO, OUTPUT);     // Configured as input when in programming mode
  digitalWrite(RST, HIGH);  // Level shifter is inverting, this shuts off 12V
  Serial.begin(9600);
   Serial.println("reanimator attiny");
}

void loop() {
  
 //  if (Serial.available() > 0) {
    Serial.read();
    pinMode(SDO, OUTPUT);     // Set SDO to output
    digitalWrite(SDI, LOW);
    digitalWrite(SII, LOW);
    digitalWrite(SDO, LOW);
    digitalWrite(RST, HIGH);  // 12v Off
    digitalWrite(VCC, HIGH);  // Vcc On
    delayMicroseconds(20);
    digitalWrite(RST, LOW);   // 12v On
    delayMicroseconds(10);
    pinMode(SDO, INPUT);      // Set SDO to input
    delayMicroseconds(300);
    unsigned int sig = readSignature();
    Serial.print("Signature is: ");
    Serial.println(sig, HEX);
    readFuses();
    if (sig == ATTINY13) {
 // для "хитрожопых" attiny13 , затерем сначала в FF  
      writeFuse(LFUSE, 0xFF);
      writeFuse(HFUSE, 0xFF);
      
      writeFuse(LFUSE, 0x6A);
      writeFuse(HFUSE, 0xFF);
    } else if (sig == ATTINY24 || sig == ATTINY44 || sig == ATTINY84 ||
               sig == ATTINY25 || sig == ATTINY45 || sig == ATTINY85 || sig == 0xFFFF ) {
      writeFuse(LFUSE, 0x62);
      writeFuse(HFUSE, 0xDF);
      writeFuse(EFUSE, 0xFF);
    }
    readFuses();
    digitalWrite(SCI, LOW);
    digitalWrite(VCC, LOW);    // Vcc Off
    digitalWrite(RST, HIGH);   // 12v Off
 // }
 Serial.println("delay 5sec");
 delay(5000);
}

byte shiftOut (byte val1, byte val2) {
  int inBits = 0;
  //Wait until SDO goes high
  while (!digitalRead(SDO))
    ;
  unsigned int dout = (unsigned int) val1 << 2;
  unsigned int iout = (unsigned int) val2 << 2;
  for (int ii = 10; ii >= 0; ii--)  {
    digitalWrite(SDI, !!(dout & (1 << ii)));
    digitalWrite(SII, !!(iout & (1 << ii)));
    inBits <<= 1;
    inBits |= digitalRead(SDO);
    digitalWrite(SCI, HIGH);
    digitalWrite(SCI, LOW);
  }
  return inBits >> 2;
}

void writeFuse (unsigned int fuse, byte val) {
  shiftOut(0x40, 0x4C);
  shiftOut( val, 0x2C);
  shiftOut(0x00, (byte) (fuse >> 8));
  shiftOut(0x00, (byte) fuse);
}

void readFuses () {
  byte val;
        shiftOut(0x04, 0x4C);  // LFuse
        shiftOut(0x00, 0x68);
  val = shiftOut(0x00, 0x6C);
  Serial.print("LFuse: ");
  Serial.print(val, HEX);
        shiftOut(0x04, 0x4C);  // HFuse
        shiftOut(0x00, 0x7A);
  val = shiftOut(0x00, 0x7E);
  Serial.print(", HFuse: ");
  Serial.print(val, HEX);
        shiftOut(0x04, 0x4C);  // EFuse
        shiftOut(0x00, 0x6A);
  val = shiftOut(0x00, 0x6E);
  Serial.print(", EFuse: ");
  Serial.println(val, HEX);
}

unsigned int readSignature () {
  unsigned int sig = 0;
  byte val;
  for (int ii = 1; ii < 3; ii++) {
          shiftOut(0x08, 0x4C);
          shiftOut(  ii, 0x0C);
          shiftOut(0x00, 0x68);
    val = shiftOut(0x00, 0x6C);
    sig = (sig << 8) + val;
  }
  return sig;
}

Еще какойто скетч  восстановление Fuse   AVR_High_voltage_Serial_Programmer.ino 

// AVR High-voltage Serial Programmer
// Originally created by Paul Willoughby 03/20/2010
// http://www.rickety.us/2010/03/arduino-avr-high-voltage-serial-programmer/
// Inspired by Jeff Keyzer http://mightyohm.com
// Serial Programming routines from ATtiny25/45/85 datasheet

// Desired fuse configuration
//#define  HFUSE  0xDF   // Defaults for ATtiny25/45/85         DF  62
//#define  LFUSE  0x62


#define  HFUSE  0xFF   // Defaults for ATtiny13       6A  FF    
#define  LFUSE  0x6A

#define  RST     13    // Output to level shifter for !RESET from transistor to Pin 1
#define  CLKOUT  12    // Connect to Serial Clock Input (SCI) Pin 2
#define  DATAIN  11    // Connect to Serial Data Output (SDO) Pin 7
#define  INSTOUT 10    // Connect to Serial Instruction Input (SII) Pin 6
#define  DATAOUT  9    // Connect to Serial Data Input (SDI) Pin 5 
#define  VCC      8    // Connect to VCC Pin 8




int inByte = 0;         // incoming serial byte Computer
int inData = 0;         // incoming serial byte AVR

void setup()
{
  // Set up control lines for HV parallel programming
  pinMode(VCC, OUTPUT);
  pinMode(RST, OUTPUT);
  pinMode(DATAOUT, OUTPUT);
  pinMode(INSTOUT, OUTPUT);
  pinMode(CLKOUT, OUTPUT);
  pinMode(DATAIN, OUTPUT);  // configured as input when in programming mode
  
  // Initialize output pins as needed
  digitalWrite(RST, HIGH);  // Level shifter is inverting, this shuts off 12V
  
  // start serial port at 9600 bps:
  Serial.begin(19200);
  
  establishContact();  // send a byte to establish contact until receiver responds 
  
}


void loop()
{
  // if we get a valid byte, run:
  if (Serial.available() > 0) {
    // get incoming byte:
    inByte = Serial.read();
    Serial.println(byte(inByte));
    Serial.println("Entering programming Mode\n");

    // Initialize pins to enter programming mode
    pinMode(DATAIN, OUTPUT);  //Temporary
    digitalWrite(DATAOUT, LOW);
    digitalWrite(INSTOUT, LOW);
    digitalWrite(DATAIN, LOW);
    digitalWrite(RST, HIGH);  // Level shifter is inverting, this shuts off 12V
    
    // Enter High-voltage Serial programming mode
    digitalWrite(VCC, HIGH);  // Apply VCC to start programming process
    delayMicroseconds(20);
    digitalWrite(RST, LOW);   //Turn on 12v
    delayMicroseconds(10);
    pinMode(DATAIN, INPUT);   //Release DATAIN
    delayMicroseconds(300);
    
    //Programming mode
    
    readFuses();
    
  Serial.println("Writing hfuse lfuse FF FF");  
    shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, 0x40, 0x4C);
    shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, 0xFF, 0x2C);
    shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, 0x00, 0x74);
    shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, 0x00, 0x7C);  

    shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, 0x40, 0x4C);
    shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, 0xFF, 0x2C);
    shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, 0x00, 0x64);
    shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, 0x00, 0x6C);
    
 readFuses();
 
    //Write hfuse
    Serial.println("Writing hfuse");
    shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, 0x40, 0x4C);
    shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, HFUSE, 0x2C);
    shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, 0x00, 0x74);
    shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, 0x00, 0x7C);
    
    //Write lfuse
    Serial.println("Writing lfuse\n");
    shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, 0x40, 0x4C);
    shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, LFUSE, 0x2C);
    shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, 0x00, 0x64);
    shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, 0x00, 0x6C);

    readFuses();    
    
    //Write lfuse
/*Serial.println("Writing lfuse\n");
shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, 0x40, 0x4C);
shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, LFUSE, 0x2C);
shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, 0x00, 0x64);
shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, 0x00, 0x6C);
*/

//Erase device
Serial.println("Erase device\n");
shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, 0x80, 0x4C);
shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, 0x00, 0x64);
shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, 0x00, 0x6C);
while (!digitalRead(DATAIN));

readFuses();
    
    Serial.println("Exiting programming Mode\n");
    digitalWrite(CLKOUT, LOW);
    digitalWrite(VCC, LOW);
    digitalWrite(RST, HIGH);   //Turn off 12v
  }
}


void establishContact() {
  while (Serial.available() <= 0) {
    Serial.println("press SPACE and ENTER ");   // send an initial string
    delay(1000);
  }
}

int shiftOut2(uint8_t dataPin, uint8_t dataPin1, uint8_t clockPin, uint8_t bitOrder, byte val, byte val1)
{
	int i;
        int inBits = 0;
        //Wait until DATAIN goes high
        while (!digitalRead(DATAIN));
        
        //Start bit
        digitalWrite(DATAOUT, LOW);
        digitalWrite(INSTOUT, LOW);
        digitalWrite(clockPin, HIGH);
  	digitalWrite(clockPin, LOW);
        
	for (i = 0; i < 8; i++)  {
                
		if (bitOrder == LSBFIRST) {
			digitalWrite(dataPin, !!(val & (1 << i)));
                        digitalWrite(dataPin1, !!(val1 & (1 << i)));
                }
		else {
			digitalWrite(dataPin, !!(val & (1 << (7 - i))));
                        digitalWrite(dataPin1, !!(val1 & (1 << (7 - i))));
                }
                inBits <<=1;
                inBits |= digitalRead(DATAIN);
                digitalWrite(clockPin, HIGH);
		digitalWrite(clockPin, LOW);
                
	}

        
        //End bits
        digitalWrite(DATAOUT, LOW);
        digitalWrite(INSTOUT, LOW);
        digitalWrite(clockPin, HIGH);
        digitalWrite(clockPin, LOW);
        digitalWrite(clockPin, HIGH);
        digitalWrite(clockPin, LOW);
        
        return inBits;
}

void readFuses(){
     //Read lfuse
    shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, 0x04, 0x4C);
    shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, 0x00, 0x68);
    inData = shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, 0x00, 0x6C);
    Serial.print("lfuse reads as ");
    Serial.println(inData, HEX);
    
    //Read hfuse
    shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, 0x04, 0x4C);
    shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, 0x00, 0x7A);
    inData = shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, 0x00, 0x7E);
    Serial.print("hfuse reads as ");
    Serial.println(inData, HEX);
    
    //Read efuse
    shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, 0x04, 0x4C);
    shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, 0x00, 0x6A);
    inData = shiftOut2(DATAOUT, INSTOUT, CLKOUT, MSBFIRST, 0x00, 0x6E);
    Serial.print("efuse reads as ");
    Serial.println(inData, HEX);
    Serial.println(); 
}

 

ПавеJI
Offline
Зарегистрирован: 01.05.2018

Всем доброго времени суток. Как-то месяц-полтора назад спрашивал тут по поводу прошивки голой attiny85, хотел реализовать на ней стробоскоп-моргалку. "Код" данного устройства был простецким 

int led1 = 2;
int led2 = 3;
int led3 = 4;

void setup() {
pinMode (led1, OUTPUT);
pinMode (led2, OUTPUT);
pinMode (led3, OUTPUT);


digitalWrite(0, LOW);
digitalWrite(1, LOW);
digitalWrite(2, LOW);

}

void loop() {
  
 digitalWrite(led1, HIGH);
        delay(45);
    digitalWrite(led1, LOW);
        delay(45);
    digitalWrite(led1, HIGH);
        delay(45);
    digitalWrite(led1, LOW);
        delay(45);
    digitalWrite(led1, HIGH);
        delay(45);
    digitalWrite(led1, LOW);
        delay(45);
    digitalWrite(led1, HIGH);
        delay(45);
    digitalWrite(led1, LOW);
        delay(45);
    digitalWrite(led1, HIGH);
        delay(45);
    digitalWrite(led1, LOW);
        delay(150); 
          
    digitalWrite(led2, HIGH);
        delay(45);
    digitalWrite(led2, LOW);
        delay(45);
    digitalWrite(led2, HIGH);
        delay(45);
    digitalWrite(led2, LOW);
        delay(45);
    digitalWrite(led2, HIGH);
        delay(45);
    digitalWrite(led2, LOW);
        delay(45);
    digitalWrite(led2, HIGH);
        delay(45);
    digitalWrite(led2, LOW);
        delay(45);
    digitalWrite(led2, HIGH);
        delay(45);
    digitalWrite(led2, LOW);
        delay(150); 

    digitalWrite(led3, HIGH);
        delay(45);
    digitalWrite(led3, LOW);
        delay(45);
    digitalWrite(led3, HIGH);
        delay(45);
    digitalWrite(led3, LOW);
        delay(45);
    digitalWrite(led3, HIGH);
        delay(45);
    digitalWrite(led3, LOW);
        delay(45);
    digitalWrite(led3, HIGH);
        delay(45);
    digitalWrite(led3, LOW);
        delay(45);
    digitalWrite(led3, HIGH);
        delay(45);
    digitalWrite(led3, LOW);
        delay(150); 


}

Много народу написало что "код" #авно (я этого не и скрывал), используй циклы, и тогда все влезет на тини13 и тд. С циклами раньше не работал, да и скилл в программировании у меня совсем низкий, но решил сейчас попробовать. Но че-то не выходит, устройство моргает, но не так как планировалось. То что навоял прилагаю. Кому не сложно прошу помочь.

int led1 = 2;
int led2 = 3;
int led3 = 4;

void setup() {
pinMode (led1, OUTPUT);
pinMode (led2, OUTPUT);
pinMode (led3, OUTPUT);


digitalWrite(0, LOW);
digitalWrite(1, LOW);
digitalWrite(2, LOW);
}

void loop() {

for (led1 = 0; led1 <= 5; led1 ++) {
digitalWrite(led1, HIGH);
delay(45);
digitalWrite(led1, LOW);
delay(45); 
}
delay(150);

for (led2 = 0; led2 <= 5; led2 ++) {
digitalWrite(led2, HIGH);
delay(45);
digitalWrite(led2, LOW);
delay(45); 
}
delay(150);

for (led3 = 0; led3 <= 5; led3 ++) {
digitalWrite(led3, HIGH);
delay(45);
digitalWrite(led3, LOW);
delay(45); 
}
delay(150);
}

 

СергейНСК
Offline
Зарегистрирован: 22.11.2014

В строчках 18, 26, 34 замени ledX на любую другую переменную типа int или byte. Хоть заработает. Но так тоже далеко не оптимально

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

slider пишет:

не восстанавливаются fuse avr attiny attiny13a (для гугла
sp;


Большое спасибо. Однозначно надо добавить в шапку темы и в фак. Вполне возможно, китайцы реверс инжинирингом или тупо шпионажем получили топологию тини13, но с ошибками.
Насчёт затирания флеш ff перед записью - это к бы обычная практика. Чистая еепром это все единицы.
Почему у вас просыпалась тини в ардуине поняли? Постоянно молотит таймер, который считает delay() и millis(). Он-то и пробуждает каждую миллисекунду вашу тиньку. Его надо останавливать.

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

ПавеJI пишет:

Всем доброго времени суток. Как-то месяц-полтора назад спрашивал тут по поводу прошивки голой attiny85, хотел реализовать на ней стробоскоп-моргалку. "Код" данного устройства был простецким 


А чего вы хотите добиться? Чтобы они у вас последовательно включались или чтобы все три почти в разнобой одновременно вспыхивали? Сейчас они у вас будет примерно так: первый проморгал, потом второй проморгал, потом третий проморгал.

ПавеJI
Offline
Зарегистрирован: 01.05.2018

СергейНСК пишет:
В строчках 18, 26, 34 замени ledX на любую другую переменную типа int или byte. Хоть заработает. Но так тоже далеко не оптимально

 

Ну а как га ваш взляд это оптимально реальзовать?

СергейНСК
Offline
Зарегистрирован: 22.11.2014

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

xDriver
xDriver аватар
Offline
Зарегистрирован: 14.08.2015

ПавеJI пишет:

СергейНСК пишет:
В строчках 18, 26, 34 замени ledX на любую другую переменную типа int или byte. Хоть заработает. Но так тоже далеко не оптимально

 

Ну а как га ваш взляд это оптимально реальзовать?

по субботам я добрый

uint8_t led[] = {2, 3, 4};

void setup() {
  for (uint8_t i = 0; i < sizeof(led); i++) {
    pinMode(led[i], OUTPUT);
    digitalWrite(led[i], LOW);
  }
}

void loop() {
  for (uint8_t i = 0; i < sizeof(led); i++) {
    for (uint8_t j = 0; j < 5; j++) {
      digitalWrite(led[i], HIGH);
      delay(45);
      digitalWrite(led[i], LOW);
      delay(45);
    }
    delay(150);
  }
}

 

ПавеJI
Offline
Зарегистрирован: 01.05.2018

xDriver пишет:

ПавеJI пишет:

СергейНСК пишет:
В строчках 18, 26, 34 замени ledX на любую другую переменную типа int или byte. Хоть заработает. Но так тоже далеко не оптимально

 

Ну а как га ваш взляд это оптимально реальзовать?

по субботам я добрый

uint8_t led[] = {2, 3, 4};

void setup() {
  for (uint8_t i = 0; i < sizeof(led); i++) {
    pinMode(led[i], OUTPUT);
    digitalWrite(led[i], LOW);
  }
}

void loop() {
  for (uint8_t i = 0; i < sizeof(led); i++) {
    for (uint8_t j = 0; j < 5; j++) {
      digitalWrite(led[i], HIGH);
      delay(45);
      digitalWrite(led[i], LOW);
      delay(45);
    }
    delay(150);
  }
}

Крайне признателен за такой подгон ))) Но, насколько я понимаю, реализовать данную моргалку на 13 тиньке не выйдет, ибо скетч использует 1066 байт.(((

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

ПавеJI пишет:

Крайне признателен за такой подгон ))) Но, насколько я понимаю, реализовать данную моргалку на 13 тиньке не выйдет, ибо скетч использует 1066 байт.(((

У меня IDE после екомпиляции выдало такое для ATtiny13 :

Скетч использует 462 байт (45%) памяти устройства. Всего доступно 1024 байт.
Глобальные переменные используют 8 байт (12%) динамической памяти, оставляя 56 байт для локальных переменных. Максимум: 64 байт.
 
ПавеJI
Offline
Зарегистрирован: 01.05.2018

Joiner пишет:

ПавеJI пишет:

Крайне признателен за такой подгон ))) Но, насколько я понимаю, реализовать данную моргалку на 13 тиньке не выйдет, ибо скетч использует 1066 байт.(((

У меня IDE после екомпиляции выдало такое для ATtiny13 :

Скетч использует 462 байт (45%) памяти устройства. Всего доступно 1024 байт.
Глобальные переменные используют 8 байт (12%) динамической памяти, оставляя 56 байт для локальных переменных. Максимум: 64 байт.
 

Прошу прощения, сначала конпилировал для Nano, для 13 тини Ide посчитал :

Скетч использует 456 байт (44%) памяти устройства. Всего доступно 1024 байт.

Глобальные переменные используют 8 байт динамической памяти. 

ELITE
ELITE аватар
Offline
Зарегистрирован: 11.01.2018

привет всем.

тини 13, детский ночник 

на борту РЖБ диод
3 кнопки на резисторном делителе и 1 прямая

скетч занимает 874 байта, но хочется еще ужать

т.к. хочу добавить еще двигатель для вращения и мп3 плеер для мазычки... но места маловато остается для реализации всех хотелок...

//а да, тини 25/45/85 не предлагать (хочу вместить в 13ю :) тем более она уже запяна а другие надо ехать покупать)

#include <avr/io.h>
#include <stdlib.h>
#include <avr/interrupt.h>
#include <util/delay.h>


#define LED1_OFF PORTB &= ~_BV(PB0) 
#define LED2_OFF PORTB &= ~_BV(PB1) 
#define LED3_OFF PORTB &= ~_BV(PB2) 
 
#define LED1_ON PORTB |= _BV(PB0) 
#define LED2_ON PORTB |= _BV(PB1) 
#define LED3_ON PORTB |= _BV(PB2) 

#define ANL_IN _BV(PB3) //ADC3
#define DIG_IN _BV(PB4) //DDC4

uint8_t counter=0,  j=0,  ci=0;
uint8_t lev_ch[]={0,0,0};
uint8_t ch[3];
uint8_t mods = 0; // выбор режима
uint8_t vol = 0;

uint8_t levels[] = {0, 1, 3, 5, 7, 10, 13, 17, 21, 26, 32, 40, 48, 58, 68, 80, 92, 106, 120, 140, 164, 192, 224, 255};  //коррекция уровней видимой яркости

const uint8_t keyValues[] PROGMEM = { 95,105,120,135,155,180,225 };

uint8_t getKey(uint8_t avalue) {
    for (uint8_t i = 0; i < 7; i++)
        if (avalue <= keyValues[i]) return i;
    return 0x07;
}

ISR(TIM0_OVF_vect){
 /*программный ШИМ*/
 counter>=lev_ch[0]?LED1_OFF:LED1_ON;
 counter>=lev_ch[1]?LED2_OFF:LED2_ON;
 counter>=lev_ch[2]?LED3_OFF:LED3_ON;
 counter++;

}
ISR(ADC_vect){// срабатывает при каждом окончании замера напряжения
   mods=getKey(ADCH);
}

int main(void)
{
 DDRB=0b00000111; // установка PortB пины 0 1 2 выходы
 PORTB |= DIG_IN; // Включаем подтягивающий (Pull-UP) резистор для пина
 TCCR0B = _BV(CS00);  // таймер работает без предделителя 
 TIMSK0 = _BV(TOIE0); // прерывания по переполнению таймера разрешены  

 ADMUX = 0b00100011; // опорное напряжение - VCC  левое ориентирование данных  выбран вход ADC2(pb4) (на нём висит перем. резистор)

 ADCSRA = 0b11101111; // АЦП включен  запуск преобразования  режим автоизмерения  прерывание по окончанию преобразования  частота CLK/128
 ADCSRB = 0b00000000; // режим автоизмерения: постоянно запущено
 DIDR0 |= ANL_IN;     // запрещаем цифровой вход на ноге аналогового входа

 sei();
 
/*******************************************************************************************************/
while (1)   //бесконечная шарманка
{
  
  if( !(PINB & DIG_IN) ) {  // Проверяем нажата ли кнопка
    mods = mods+10;         // режимы авто/ручной
    }  
  /****************************************/   
  // Ручные режимы    //   синий  зелены  красный
  LED1_OFF; LED2_OFF; LED3_OFF;
switch (mods) {
/*ручной*/
    case 1:
      lev_ch[0]=lev_ch[1]=lev_ch[2]=60;       break;
    case 2:
                        LED3_ON;          break;
    case 3:
                LED2_ON;                  break;
    case 4:
                LED2_ON;   LED3_ON;       break;
    case 5:
      LED1_ON;                            break;
    case 6:
      LED1_ON;             LED3_ON;       break;
    case 7:
      LED1_ON;             LED2_ON;       break;
    case 8:
      LED1_ON;  LED2_ON;   LED3_ON;       break;
 /* авто */
    case 11:
          if( ci==0) {      lev_ch[0]=levels[j];      LED2_OFF;              LED3_ON;        } 
         if( ci==1) {      LED1_ON;                  LED2_OFF;              lev_ch[2]=levels[23-j];      } 
         if( ci==2) {      LED1_ON;                  lev_ch[1]=levels[j];   LED3_OFF;                 } 
         if( ci==3) {      lev_ch[0]=levels[23-j];   LED2_ON;               LED3_OFF;                 } 
         if( ci==4) {      LED1_OFF;                 LED2_ON;               lev_ch[2]=levels[j];         } 
         if( ci==5) {      LED1_OFF;                 lev_ch[1]=levels[23-j];   LED3_ON;        } 
         
         if (++j>23) {j=0; ci++; if(ci==6) ci=0;}
        _delay_ms (250); 
    break;
    case 12:
   //  радуга 
        LED1_OFF;  LED2_OFF;  LED3_OFF;  _delay_ms (500);      //-
        LED1_OFF;  LED2_OFF;  LED3_ON;  _delay_ms (2500);   //К
        LED1_OFF;  lev_ch[1]=64;  LED3_ON;  _delay_ms (2500);  //О
        LED1_OFF;  lev_ch[1]=127;  LED3_ON;  _delay_ms (2500); //Ж
        LED1_OFF;  LED2_ON;  LED3_OFF;  _delay_ms (2500);   //З
        lev_ch[0]=127;  lev_ch[1]=32;  lev_ch[2]=32;  _delay_ms (2500); //Г
        LED1_ON;  LED2_OFF;  LED3_OFF;  _delay_ms (2500);   //С
        LED1_ON;  LED2_OFF;  lev_ch[2]=127;  _delay_ms (2500); //Ф
        LED1_OFF;  LED2_OFF;  LED3_OFF;  _delay_ms (500);      //-
    
    break;
    case 13:
    break;
    case 14:
    break;
    case 15:
    break;
    case 16:
    break;
    case 17:
    break;
    case 18:
    break;
  }
  
  
  
    
} 
}

 

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

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

ELITE
ELITE аватар
Offline
Зарегистрирован: 11.01.2018

pittyalex пишет:
Раньше когда разбирался заметил, что switch генерирует очень много кода. Попробуйте обойтись без него. А так - имхо без перехода на ассемблер вряд-ли получится существенно сократить код.

вот какраз 16 IF-ов было до switch 

switch мне дал почти 120 байт экономии

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

xDriver
xDriver аватар
Offline
Зарегистрирован: 14.08.2015

коль так, в case 11: замените ифы на еще один switch(ci).

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

Да, ещё можно макросы ledX_On и Off заменить на запись в порт. Тогда в некоторых местах уменьшится количество команд с 3х до 1.
И вообще, оно у вас уже работает? Сдается мне что оно не везде работает так, как вы задумали. В частности, если у вас в регистры шип что-то записано, то никакой ледон, ледофф не поможет. На следующем тике таймера значение порта изменится в соответствии с шимом.
Включение-ввключение светодиода в этом случае надо делать изменением значения Ви регистре шим

ELITE
ELITE аватар
Offline
Зарегистрирован: 11.01.2018

pittyalex пишет:
Да, ещё можно макросы ledX_On и Off заменить на запись в порт. Тогда в некоторых местах уменьшится количество команд с 3х до 1. И вообще, оно у вас уже работает? Сдается мне что оно не везде работает так, как вы задумали. В частности, если у вас в регистры шип что-то записано, то никакой ледон, ледофф не поможет. На следующем тике таймера значение порта изменится в соответствии с шимом. Включение-ввключение светодиода в этом случае надо делать изменением значения Ви регистре шим

да, код полностью работает

ШИМ программный - поэтому он не мешает переопределению в теле while 

изначально было задание уровня, но это съедало под 80 байт аж!

Chip_SET
Offline
Зарегистрирован: 27.01.2015

ОФФ: Киньте тапком где прочитать про инициализацию программы при включении, а то гуголь сломался. Пример: в контроллере 2 проги, медленно мигаем светодиодом и быстро. И при включении как это менять. Если не нажимали то 1е мигание только работает, если была нажата то только второе.

ELITE
ELITE аватар
Offline
Зарегистрирован: 11.01.2018

Chip_SET пишет:

ОФФ: Киньте тапком где прочитать про инициализацию программы при включении, а то гуголь сломался. Пример: в контроллере 2 проги, медленно мигаем светодиодом и быстро. И при включении как это менять. Если не нажимали то 1е мигание только работает, если была нажата то только второе.

код выполняется последовательно - как вы зададите - так и будет

если брать простую логику:
то вначале мк должен проверить порт с кнопкой, включена или нет она
а дальше IF()...else... 

вот и всё...

Jeka_M
Jeka_M аватар
Offline
Зарегистрирован: 06.07.2014

Chip_SET пишет:

ОФФ: Киньте тапком где прочитать про инициализацию программы при включении, а то гуголь сломался. Пример: в контроллере 2 проги, медленно мигаем светодиодом и быстро. И при включении как это менять. Если не нажимали то 1е мигание только работает, если была нажата то только второе.

В контроллере не может быть "две проги". "Прога" всегда одна, инициализируется с самого начала и выполняется последовательно. Вы сами в этой "проге" должны написать условия if...else в том месте, где это нужно. Например в начале выполнения программы.

Chip_SET
Offline
Зарегистрирован: 27.01.2015

Ну про бред данной задумки я сразу и подумал. Вы поставили точку.  :)

scilics
Offline
Зарегистрирован: 16.01.2019

Всем привет, возможна ли реализация выполнения кода для Attiny13A при долгом нажатии кнопки для на выводе INT0 с включенным прирыванием?

scilics
Offline
Зарегистрирован: 16.01.2019

Всем привет, возможна ли реализация выполнения кода для Attiny13A при долгом нажатии кнопки для на выводе INT0 с включенным прирыванием?

slider
Offline
Зарегистрирован: 17.06.2014

естественно .

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

scilics
Offline
Зарегистрирован: 16.01.2019

Вот код, почему то при долгом нажатии в сон не уходит( возможно миллис не работает или конфликт с прерываниями, что может быть не так? Плата Attiny13 взята отсюда https://raw.githubusercontent.com/sleemanj/optiboot/master/dists/package_gogo_diy_attiny_index.json

#include <avr/io.h>
#include <avr/interrupt.h> //прерывания
#include <avr/sleep.h> //режимы сна
unsigned long previousMillis = 0; 
byte regim = 1;
byte flag = 0;
byte val = 0;

void setup()
{
  DDRB |= (1 << PB0); 
  DDRB &= ~(1 << PB1); //PB1 на вход
  
  TCCR0A = 0x83;//шим 
  TCCR0B = 0x01;
  OCR0A = 0x00;
    
  int_ini(); // настройка прерывания инт0
  set_sleep_mode(SLEEP_MODE_PWR_DOWN); // установка метода сна
  sei(); // разрешаем прерывания
}

void int_ini() {
  GIMSK |= (1 << INT0); // разрешение внешних прерываний. INT0 PB1
}

void sleep ()
{
   sei(); // разрешаем прерывания
   ADCSRA &= ~(1 << ADEN); // перед сном отключим АЦП
   ACSR |= (1 << ACD); // и компаратор
   sleep_enable(); // разрешаем сон
   sleep_cpu(); // сон. 
}

ISR (INT0_vect) {}


void loop()
{
cli(); // запр прерывания
if (digitalRead(1) == LOW && flag == 1)
  {
  flag = 0; 
  }

if (digitalRead(1) == LOW) 
  {
  if (millis() - previousMillis >500)    
    { 
    previousMillis = millis();     
    val++; 
    } 
    } 
     if(val >= 5) 
    {
    sleep();
    }
  if (digitalRead(1) == HIGH && flag == 0)
    {
    sleep_disable();
    delay(50);
    TCCR0A = 0x83;
    regim++;
    flag = 1;

  if (regim > 7) //количество режимов
    {
      regim = 1; 
    }
  }

  if (regim == 1) //1 режим
  {
    OCR0A = 20;
  }
  if (regim == 2) //2 режим
  {
    OCR0A = 255;
  }
  if (regim == 3) //3 режим
  {
    OCR0A = 200;
  }
  if (regim == 4) //4 режим
  {
    OCR0A = 150;
  }
  if (regim == 5) //5 режим
  {
    OCR0A = 100;
  }
  if (regim == 6) //6 режим
  {
    OCR0A = 50;
  }
  if (regim == 7) //7 режим
  {
  sleep();
  }
}

 

releyshic
Offline
Зарегистрирован: 20.11.2015

scilics пишет:

Вот код

ISR (INT0_vect) {}

Насколько я понимаю в скобочках должно быть написан код, который будет выполняться при прерывании, а там пусто

scilics пишет:

почему то при долгом нажатии в сон не уходит

а при коротком уходит?

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

if (digitalRead(1) == LOW && flag == 1)

043   {
044   flag = 0;
045   }
046  
047 if (digitalRead(1) == LOW)
048   {
049   if (millis() - previousMillis >500)   
050     {
051     previousMillis = millis();    
052     val++;
053     }
054     }
055      if(val >= 5)
056     {
057     sleep();
058     }
059   if (digitalRead(1) == HIGH && flag == 0)
060     {
061     sleep_disable();
062     delay(50);
063     TCCR0A = 0x83;
064     regim++;
065     flag = 1;

 

 

 

 

 

 

scilics
Offline
Зарегистрирован: 16.01.2019

Переделал код, перешел на конструкцию с while (1) в сон уходит. Но при новой подаче питания на тиньку ждрет 4 mA? как сделать чтобы при вкл. питания был сон?

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

scilics пишет:

Переделал код, перешел на конструкцию с while (1) в сон уходит. Но при новой подаче питания на тиньку ждрет 4 mA? как сделать чтобы при вкл. питания был сон?

Ну очевидно же- в setup некой переменной ставите значение уснуть и сразу в начале loop её проверяете и уходите в сон.

scilics
Offline
Зарегистрирован: 16.01.2019

Супер всё работает! Ну для первой программы не очевидно))

satelit 2
Offline
Зарегистрирован: 04.12.2016

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

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

satelit 2 пишет:

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

ну тут несколько вариантов:

- вытаскивать из панельки МК каждый раз для перепрошивки

- прошивать как есть вместе с исполнительными устройствами - как повезет - я так 2 шт погубил

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

satelit 2
Offline
Зарегистрирован: 04.12.2016

спасибо БОЛЬШОЕ. если я смогу на дипе собрать и доработать прототип, и в оконцовке залить на смд, то будет чудо. я так понял ресет нельзя использовать как рабочий выход? у меня две тиньки, одна дип для программирования, и вторая смд для законченной версии. так пологать у меня одно право на ошибку

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

satelit 2 пишет:

я так понял ресет нельзя использовать как рабочий выход?

можно, но один раз :) потом уже не перепрошить 

satelit 2 пишет:

 так пологать у меня одно право на ошибку

ну....я всегда штук по 5 беру на Али, так и дешевле и прав на ошибку больше.

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

Через почти год работы помер RF433 передатчик уличного термометра на Attiny85 и DS18B20. Собрал новый. Из аппаратных изменений: транзисторный ключ на передатчик, повышайка на 5 вольт (до этого была на 3.3 вольта) для увеличения радиуса действия. Заодно скетч переписал - добавил контроль СRC при получении температуры. Отправка как и было каждые ~17 минут.

При питании от CR2032 потребление в спящем режиме ~110 мкА. При питании от 5 вольт ~85 мкА. Если выкинуть повышайку можно еще примерно 20 мкА убрать, но надо быть уверенным что в морозы элемент питания будет работать.

#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 1111

#define ds_pin PB4
OneWire ds18b20(ds_pin);

#define en_pin PB0

#define rf_pin PB3
#define RC_BIT rf_pin

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

void setup () {
  ExecFunc();
}

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

void ExecFunc() {
  word currT = getTemp();
  if (currT != errTemp) {
    currT += 11500;
    pinMode(en_pin, OUTPUT); digitalWrite(en_pin, HIGH); // RF ON
    pinMode(rf_pin, OUTPUT); digitalWrite(rf_pin, LOW); // OFF data RF
    sendRC(currT);
  }
  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(1000);
  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)) {
    outTemp = (~outTemp) + (word)1;
    outTemp = (((word)6 * outTemp) + outTemp / (word)4) / (word)10;
  } else {
    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);
  }
}