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

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

Итак, уже давненько появился способ программировать маленькие, дешёвые, маложрущие и доступные микрухи ATtiny13A.

Тут я Вам расскажу как можно зашивать дуиновские скетчи.

Итак, для начала нам нужно скачать данный архив(взято отсюда) положить файлы по адресу "\Documents\Arduino\hardware\" должно получится чтото типо "C:\Users\Администратор\Documents\Arduino\hardware\attiny13\cores\core13". Потом  ну и в настройках платы выбрать attiny13 9.6 мГц, на других частотах почему то все задержки не такие как задаю, на 128 кГц всё в 2-3 раза быстрее.

Далее нам нужна сама микруха :) Имеете? отлично. Теперь нам нужно узнать как при помощи Arduino прошить тиньку, более подробней здесь.

Итак, зашили blink - работает, отлично, я Вас поздравляю, "это маленький шаг для человека и большой шаг для человечества" :) Как вы уже заметили скетч стал заметно легче ежели для UNO, это связано тем что урезаны большинство дуиновских функций.

100% поддержываются следущие: 

pinMode()
digitalWrite()
digitalRead()
analogRead()
analogWrite()
shiftOut()
pulseIn()
millis()
micros()
delay()
delayMicroseconds()

Итак как мы ещё увидели доступно всего 1024 байта, но ведь это мало? "Вы есть много кушать" :) большинству радиолюбителей для небольшой задач типо всяких мигалок, простеньких индикаторов или прочей мелочи - более чем достаточно. Чтобы научится экономить рекомендую ознакомится, а ещё лучше изучайте AVR и Cи, я вот когда смогу побороть лень начну :)

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

Вот мой первый проект, там я получил несколько советов по оптимизации кода аля уменьшения размера скетча при той же функциональности.

Вот ещё товарищ подтянулся.

Сейчас хочу этот проект перенести на тиньку, но времени маловато, чёт работать не хочет программном моделировании, нужно спаять всё, так как бредборда не имею :( но куплю, обязательно.

Распиновка из даташита:

 

Нипаняятна? PB5 это тоже что и pin 5 или просто 5. Аналоговые входы все на которых пишет ADC* ШИМ поддерживают порты 0 и 1 ану-ка найдите их на картинке? PB5 использовать и не прибегая к танцам с бубоном не выйдет :( но если вам удастся обуздать эту ногу пишите, мне будет интересно, но незабываем что это форум Arduino.ru

Вкратце наверное всё :) всем удачи, и удачных проектов.  

ЗЫ для 5 В питания просто идеально подходит линейный стабилизатор 78L05, они просто созданы друг для друга :) тоже такой дешёвый, маленький и доступный.

 

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

Для начинающих рекомендую посетить http://sotvorimvmeste.ru/viewtopic.php?f=36&t=74 .

Статья по прошивке тиньки при помощи arduino http://razniepodelki.blogspot.com/2014/05/attiny13-arduino.html или же более детальная статья на geektimes https://geektimes.ru/post/254970/ .

UPD1 17.03.2016 Файлы ядра ищите теперь тут:
https://geektimes.ru/post/254970/#comment_8943030


Для экономии памяти первым делом научитесь пользоваться директивой препроцессора #define, к примеру код:
 

int led = 13;
//#define led 13
void setup() {                
  pinMode(led, OUTPUT);     
}

void loop() {
  digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);               // wait for a second
  digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);               // wait for a second
}
//Размер скетча в двоичном коде: 384 байт (из 1 024 байт максимум)

Можно записать немного иначе:
 

//int led = 13;
#define led 13
void setup() {                
  pinMode(led, OUTPUT);     
}

void loop() {
  digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);               // wait for a second
  digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);               // wait for a second
}
//Размер скетча в двоичном коде: 376 байт (из 1 024 байт максимум)

Экономия при этом будет 8 байт а код будет работать так же. 

Функции ардуино на Си: 

pinMode(2, OUTPUT); будет  DDRB |= (1<<2);     // устанавливаем вывод PB2 как выход  
pinMode(2, INPUT); - DDRB &= ~(1<<2);  // устанавливаем вывод PB2 как вход 
digitalWrite(2, HIGH); - PORTB |= (1<<2); // устанавливаем высокий уровень на выводе PB2             
digitalWrite(2, LOW); - PORTB &= ~(1<<2); // устанавливаем низкий уровень на выводе PB2 

//Чтение состояния(лог. 1) на порту ввода вывода:
if (digitalRead(4) == HIGH){     
...
} 
if (PINB & (1<<PINB4)){
...
}
//Чтение состояния(лог. 0) на порту ввода вывода:
if(digitalRead(4) == LOW){     
...
} 
if(!(PINB & (1<<PINB4))){
...
}

Например стандартный код:

void setup() {                
  pinMode(0, OUTPUT); // устанавливаем вывод PB0 как выход     
}
void loop() {
  digitalWrite(0, HIGH); // устанавливаем высокий уровень на выводе PB0
  delay(1000); // ждем 1000 миллисекунд
  digitalWrite(0, LOW); // устанавливаем низкий уровень на выводе PB0
  delay(1000); // ждем 1000 миллисекунд
}
// Размер скетча в двоичном коде: 376 байт (из 1 024 байт максимум)

Можно записать вот так:
 

#include <avr/io.h> // принято подключать
#include <util/delay.h> // нужна для функции _delay_ms();

int main( void )
{  // всё что до while(1){ выполняется один раз при старте
  DDRB |= (1<<0); // устанавливаем вывод PB0 как выход
  while(1){ // вечный цыкл, тоже самое что и void loop(){
    PORTB |= (1<<0); // устанавливаем высокий уровень на выводе PB0
    _delay_ms(1000); // ждем 1000 миллисекунд
    PORTB &= ~(1<<0); // устанавливаем низкий уровень на выводе PB0
    _delay_ms(1000);  // снова ждем 1000 миллисекунд
  } // конец вечного цикла
  return 0;
}
// Размер скетча в двоичном коде: 116 байт (из 1 024 байт максимум)

При этом нехило сэкономить память.

Функция analogRead(); записывается следующим образом:

int Volts = 0; // Вольтметр
void setup()
{
}
void loop()
{
 Volts = analogRead_C(2); // РВ4 в ATtiny13
}

unsigned int analogRead_C(byte channel){  
  ADMUX = channel; // ADC pin
  ADCSRA |= 1<<ADEN;
  ADCSRA |= 1<<ADSC;
  while(!(ADCSRA & (1<<ADIF)));
  ADCSRA |= 1<<ADIF;
  byte low  = ADCL;
  byte high = ADCH;
  ADCSRA &= ~(1 << ADEN);  // отключаем АЦП, для уменьшения энергопотребления
  return (high << 8) | low;
}

EEPROM.write(addr, val); и EEPROM.read(address);:

#include <avr/eeprom.h> // не забываем подключить
int Address = 0;
byte Data = 255; // для экономии рекомендую использовать тип byte(диапазон 0-255)
void setup()
{
}
void loop()
{
  EEPROM_read(Address);
  EEPROM_write(Address, Data);
}
void EEPROM_write(unsigned int uiAddress, unsigned char ucData)
{
  while(EECR & (1<<EEWE)); /*Ждать завершения предыдущей записи*/
  EEAR = uiAddress; /*Проинициализировать регистры*/
  EEDR = ucData;
  EECR |= (1<<EEMWE); /*Установить флаг EEMWE*/
  EECR |= (1<<EEWE); /*Начать запись в EEPROM*/
}
unsigned char EEPROM_read(unsigned int uiAddress)
{
  while(EECR & (1<<EEWE)); /*Ждать завершения предыдущей записи*/
  EEAR = uiAddress; /* Проинициализировать регистр адреса*/
  EECR |= (1<<EERE); /*Выполнить чтение*/
  return EEDR;
}

А вот так можно писать числа в EEPROM до 65534:

#include <avr/eeprom.h> // не забываем подключить
int Address = 0;
unsigned int Data = 65534; //0...65534
void setup()
{
}
void loop()
{
  EEPROM_read(Address);
  EEPROM_write(Address, Data);
}

//Функции (с) Кэп
 
void EEPROM_write(int uiAddress, char ucData)
{
  while(EECR & (1<<EEWE)); /*Ждать завершения предыдущей записи*/
  EEAR = uiAddress; /*Проинициализировать регистры*/
  EEDR = ucData;
  EECR |= (1<<EEMWE); /*Установить флаг EEMWE*/
  EECR |= (1<<EEWE); /*Начать запись в EEPROM*/
}
 
char EEPROM_read(int uiAddress)
{
  while(EECR & (1<<EEWE)); /*Ждать завершения предыдущей записи*/
  EEAR = uiAddress; /* Проинициализировать регистр адреса*/
  EECR |= (1<<EERE); /*Выполнить чтение*/
  return EEDR;
}
 
void EEPROMWriteInt(int p_address, int p_value) // принимает 2 параметра, адресс и число 0...65534
{ // забирает 2 ячейки, так что использовать ячейки 0, 2, 4, 6...
  byte lowByte = ((p_value >> 0) & 0xFF);
  byte highByte = ((p_value >> 8) & 0xFF);
  EEPROM_write(p_address, lowByte);
  EEPROM_write(p_address + 1, highByte);
}
 
int EEPROMReadInt(int p_address) //Считывает число в диапазоне 0...65534
{ // использует 2 ячейки, так что считывает ячейки 0, 2, 4, 6...
  byte lowByte = EEPROM_read(p_address);
  byte highByte = EEPROM_read(p_address + 1);
  return ((lowByte << 0) & 0xFF) + ((highByte << 8) & 0xFF00);
}

 

 

Взято:

http://www.myrobot.ru/articles/p_avrgcc_ver.php

http://nuzhen-sovet.ru/content/optimiziruem-kod-v-arduino  // отличный туториал по программированию на С

http://myrobot.ru/forum/topic.php?forum=3&topic=239

Ещё полезные ссылки:

Как записать числа больше 255 в EEPROM

http://habrahabr.ru/post/152299/ // Програмный ШИМ

http://habrahabr.ru/post/249967/ // Как восстановить неправильно выставленные фьюзы в ATtiny

http://habrahabr.ru/post/251141/ // Программный юарт на ATtiny13

...

Будет обновляться.

Alexander
Онлайн
Зарегистрирован: 25.04.2010

К сожалению вынужденная мера. Студенты задавали вопросы, а затем удаляли содержимое первого поста, чтобы преподаватели не нашли. В результате ответы повисали в воздухе

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

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

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

Уберите пожалуйста "...если у Вас нету таких папок создайте..." и поправте цитату Армстронга "это маленький шаг для человека и большой шаг для человечества" 

Alexander
Онлайн
Зарегистрирован: 25.04.2010

Готово, поправил. В любом случае никто пальцем тыкать не будет, это ведь не форум лингвистов.

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

Спасибо, жду пополнений проектов на сабжовой микрухе.

toc
Offline
Зарегистрирован: 09.02.2013

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

хочу дуину на работу принести, еле сдерживаю себя.

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

Первая картинка с гугла, скорей всего при нажатии на кнопку горит какой-то светодиод, или же они образуют какой-то цвет... так безделушка на рандоме...

Скетч из примера в IDE, чисто для наглядности.

Где работаешь? Arduino как программатор не совсем актуально имхо http://dmitrstas.ucoz.ru/publ/chasy/programmatory/avr_usbasp/8-1-0-74

 

Densoider
Offline
Зарегистрирован: 02.11.2012

Вопросы топикстартеру и тем у кого получилось.

1. Не получается интегрировать Tiny13 в Arduino IDE. По ссылкам на проекты с 45 и 85 тинькой все пучком, а 13 не встает. У кого вышло - поделитесь куда что клали, плиз. У топикстартера - не очевидно.

2. Я НЕ хочу пользовать Ардуину как программатор. Хочу пользовать дуиновский язык и оболочку и шить напрямую через USBasp. Это возможно?

Спасибо.

maksim
Offline
Зарегистрирован: 12.02.2012

Densoider пишет:

Вопросы топикстартеру и тем у кого получилось.

1. Не получается интегрировать Tiny13 в Arduino IDE. По ссылкам на проекты с 45 и 85 тинькой все пучком, а 13 не встает. У кого вышло - поделитесь куда что клали, плиз. У топикстартера - не очевидно.

К сожалению что у вас не вышло никому не известно, так что чем делиться тоже не ясно.

Densoider пишет:

2. Я НЕ хочу пользовать Ардуину как программатор. Хочу пользовать дуиновский язык и оболочку и шить напрямую через USBasp. Это возможно?

Спасибо.

Конечно возможно. Выберите свой программатор из списка программаторов и в меню File нажимаете Upload using programmer.

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

Итак, для начала нам нужно скачать данный архив(взято отсюда) положить файлы по адресу "\Documents\Arduino\hardware\" должно получится что-то типо "C:\Users\Администратор\Documents\Arduino\hardware\attiny13\cores\core13". Потом ну и в настройках платы выбрать attiny13 9.6 мГц, на других частотах почему то все задержки не такие как задаю, на 128 кГц всё в 2-3 раза быстрее.

 

 

Кстати первый пост читали?

 

Densoider
Offline
Зарегистрирован: 02.11.2012

Приветствую. Все прочитал. Интересно, что дома под 7 все встало, а на работе под ХР не встает....

Спасибо. Что наваяю - буду постить сюда.

Densoider
Offline
Зарегистрирован: 02.11.2012

По поводу задержек - разберитесь со фьюзами в файле boards.

ИМХО там хрень какая-то.

###########################################################################
attiny13int.name=Attiny13 @ 128 KHz (internal watchdog oscillator)
attiny13int.upload.using=arduino:arduinoisp
attiny13int.upload.maximum_size=1024
attiny13int.upload.speed=250 # important for not losing connection to a slow processor
attiny13int.bootloader.low_fuses=0x7B - делитель на 8 отключен [CKDIV8=1]. Частота RC - 128 kHz
attiny13int.bootloader.high_fuses=0xFF
attiny13int.bootloader.unlock_bits=0x3F - это еще нахрена?
attiny13int.bootloader.lock_bits=0x3F - аналогично?
attiny13int.build.mcu=attiny13
attiny13int.build.f_cpu=128000 - частота честная
attiny13int.build.core=core13

###############################################################

attiny13at4.name=ATtiny13 @ 4.8MHz (internal 4.8 MHz clock)
attiny13at4.upload.using=arduino:arduinoisp
attiny13at4.bootloader.low_fuses=0x69 - тут делитель на 8 включен [CKDIV8=0]. Частота RC - 4,8 MHz
attiny13at4.bootloader.high_fuses=0xff
attiny13at4.upload.maximum_size=1024
attiny13at4.build.mcu=attiny13
attiny13at4.build.f_cpu=600000 - частота установлена правильно (поскольку включен делитель)
attiny13at4.build.core=core13
###############################################################

attiny13.name=ATtiny13 @ 9.6MHz (internal 9.6 MHz clock)
attiny13.upload.using=arduino:arduinoisp
attiny13.bootloader.low_fuses=0x7a - отключен делитель на 8 ([CKDIV8=1]). Дефолт - 0x6a
attiny13.bootloader.high_fuses=0xff
attiny13.upload.maximum_size=1024
attiny13.build.mcu=attiny13
attiny13.build.f_cpu=1200000 - при этом частота МК таки делится на 8 !!!
attiny13.build.core=core13

###############################################################

ИМХО - непонятки с задержками именно отсюда.

Densoider
Offline
Зарегистрирован: 02.11.2012

Приветствую!

На работе тоже все получилось. Есть подозрение, что беда была в том, что каталог с core/core13 был назван Attiny13 с Большой буквы. Стер все, переставил - заработало.

Самое главное, что получилось шить через USBasp! Но там выскакивает Warning - avrdude: warning: cannot set sck period. please check for usbasp firmware update.

На это надо просто забить, т.к. все шьется замечательно.

Немного геморройно с названиями выводов, надо помнить распиновку, что вывод 1 это pin 5, вывод 2 - это pin 3 и т.п.

Теперь можно Дуиновским языком писать под тиньку 13.

Теперь надо бы разобраться с таймингами, понять чему равен delay в зависимости от частоты и т.п.

Поморгал диодом, поморгал диодом с кнопки. Короче работает!

maksim
Offline
Зарегистрирован: 12.02.2012

Практика показывает, что на Attiny13 с дуиновскими функциями далеко не уедешь... уж слишком они объемные.

Densoider
Offline
Зарегистрирован: 02.11.2012

Абсолютно согласен, но Дуина - это среда для разработки своих мозгов (а не железа), посему, как завещал Ильич, которому скоро стукнет кста - "Учиться, учиться и еще раз учиться".

Бум учиться на малом, а потом и к старикам Кернигану с Ричем, глядишь подойдем. Хотелось бы. Но ASM уж точно ниасилю.

maksim
Offline
Зарегистрирован: 12.02.2012

Нет, про среду я ничего не говорю, она кстати, не имеет практически никаких ограничений - хоть на асме пишите, а вот некоторые дуиновские функции... все равно в итоге от них откажитесь.

Densoider
Offline
Зарегистрирован: 02.11.2012

Кстати, про среду.

Посмотрев указанные в топике примеры хочу задать дурацкий вопрос. Как среда переваривает/понимает  инструкции для работы с портами AVR типа - DDRB или PORTB?

Гдето внутрях смотрит в io.h?

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

Насчёт фюзов спросите тут правда если владеете английским.

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Densoider пишет:

Кстати, про среду.

Посмотрев указанные в топике примеры хочу задать дурацкий вопрос. Как среда переваривает/понимает  инструкции для работы с портами AVR типа - DDRB или PORTB?

Гдето внутрях смотрит в io.h?

Да, это можно найти в файле iotn13a.h (hardware/tools/avr/avr/include/avr)

Например, DDRB

 

#define DDRB _SFR_IO8(0x17)
 
HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013
HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013

Всем привет, стоит задача на сабже сделать генератор импульсов на частоте 22-60 кГц(тоесть нарастающая, с шагом в 1 кГц за секунку) потом нужно замолкнуть на 2 минуты и цикл повторяется.

С схемотехникой как бы всё понятно:

Я как неопытный программист тут немного запутался, как задать частоту я разобрался:



    digitalWrite(0, HIGH); 
    delayMicroseconds(f);  
    digitalWrite(0, LOW);
    delayMicroseconds(f); 

А как сделать чтобы переменная f через некоторое время принимала значение скажем f+1, потом и ещё +1...

Пробовал задать циклом:



int main( void )
{
 DDRB = 0b11111;

while(1){
// for(int f1 = 100; f1 < 1000; f1++){
  for(byte f = 22; f < 8; f--){ // 8 микросекунд это и будет частота в ~ 60 кГц, а 22 - 22 кГц
    digitalWrite(0, HIGH); 
    delayMicroseconds(f);  
    digitalWrite(0, LOW);
    delayMicroseconds(f); 
  }
  //delayMicroseconds(f1);
 //}
}
  return 0;
}

 

Но это не то, это вообще баловство, может мне подскажет кто в какую сторону смотреть?

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

 

maksim
Offline
Зарегистрирован: 12.02.2012

Ну почему же балавство... если тиня больше ничего не делает то можно и ножкой дергать в цикле, но конечно не digitalWrite'ом, а через регистры.

#define F_CPU 9600000UL  // 9.6 MHz
#include <util/delay.h>

int main( void )
{
  DDRB = 1;

  while(1)
  {
    for(byte f = 22; f < 8; f--) // 8 микросекунд это и будет частота в ~ 60 кГц, а 22 - 22 кГц
    { 
      long time = 1000000/2/f;
      for(long t = 0; t < time; t++) 
      {
        PORTB = 1;
        _delay_us(f);
        PORTB = 0;
        _delay_us(f); 
      }
    }
    _delay_ms(120000);
  }
  return 0;
}

А смотреть вам надо в сторону таймера/счетчика.

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

HWman пишет:

С схемотехникой как бы всё понятно:

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

maksim
Offline
Зарегистрирован: 12.02.2012

Ага, динамик должен стоять в цепи коллектора.

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

Ну это поправимо, вот меня волнует то, как будет вести себя динамик на меандре?

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

Постоянно цокает динамик, что-то не так... Кстати пока код отрабатываю на Arduino:







//#define F_CPU 9600000UL  // 9.6 MHz
#include <util/delay.h>

int main( void )
{
 DDRB |= (1<<4); 

  while(1)
  {
    for(int f = 22; f > 8; f--) // 8 микросекунд это и будет частота в ~ 60 кГц, а 22 - 22 кГц
    { 
      PORTB &= ~(1<<4);
      long time = 1000000/2/f;
      for(long t = 0; t < time; t++) 
      {
        PORTB |= (1<<4);
        _delay_us(f);
        PORTB &= ~(1<<4); 
        _delay_us(f); 
      }
    }
    _delay_ms(5000);  // 5 сек пауза, для тестов
  }
  return 0;
}

 

Используется 12-й пин дуинки. Вот схема как будет выглядеть когда что-то получится:

Транзистор первый который попался под руку - КТ829Б.

Пробовал частоту опускать с 22-60 кГц до 2.2-6 кГц - признаюсь честно - невыносимо долго, глушит!

maksim
Offline
Зарегистрирован: 12.02.2012

Не совсем ясно о чем вы, а ваш динамик вообще в таком диапазоне частот работает? Ведь для ультразвука специальные излучатели применяют ,а не обычные колонки.

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

Вот, что-то получилось 

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

Частота уменьшенная в 10 раз, тоесть 2.2-6 вместо 22-60 кГц для того чтобы было слышно как оно работает, больше деталей будет днём.

Вот думаю, стоит ли усложнять схему или нет? 

 

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

Случайно наткнуся на http://we.easyelectronics.ru/AVR/uart-programmnyy-na-atiny13a.html и думаю, неплохо было бы сделать юсб вольтметр для всяких поделок с сабжа + старый юсб кабель от сименса.





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

volatile uint8_t uart;
uint8_t temp;
volatile uint8_t count;
volatile uint8_t start;
volatile uint8_t c;
volatile uint8_t uart_data;
volatile uint8_t Rece_bit;
volatile uint8_t rec;
volatile uint8_t usart_r;
volatile uint8_t coef;

ISR(INT0_vect){
  rec=1;
} // Прерывание чисто для определения стартового бита при приеме,
// используется редко, можно сюда повесить что-либо еще

ISR(TIM0_COMPA_vect){
  TIMSK0=0x00;
  TCCR0B=0x00; // Единственный Таймер, используется для формирования четких промежуток
  OCR0A=0; // между битами, как при приеме так и при передачи
  c=1;
  TCNT0=0;
  TIMSK0=0x04;
  TCCR0B=0x02;
  // Значение "сброс при совпадении" загружается каждый раз из переменной
  OCR0A=coef; // Можно быстро менять скорости UART
  Rece_bit=1;
}

int lov (uint8_t data2) {
  if (count>=8){
    PORTB|=(1<<4); 
    start=0; 
    temp=0; 
    c=0; 
    count=0;
    TIMSK0=0; 
    TCCR0B=0; 
    OCR0A=0;
    goto nah;
  }

  if(c==1){
    if (start==0){
      temp=0x80; 
      start=1;
      count--; 
      goto razvet;
    }
    temp=data2;
    temp=temp>>count;
    temp=temp<<7;
razvet:
    switch(temp){
    case 0x80 : 
      PORTB&=~(1<<4); 
      break;
    case 0x00 : 
      PORTB|=(1<<4); 
      break;
    }
    count++; 
    c=0;
  }
nah:;
}

int UART_trans(uint8_t data){
  uint8_t f;
  data=~data;
  coef=115;
  TIMSK0=0x04;
  TCCR0B=0x02;
  for(f=0;f<10;f++){
    while(c==0);
    lov(data);
  }
  start=0; 
  temp=0; 
  c=0; 
  count=0;
  TIMSK0=0; 
  TCCR0B=0; 
  OCR0A=0;
  coef=0;
}

int UART_receiv(void){
  uint8_t a;
  usart_r=0;

  MCUCR=0x02; // INT0 Interrupt
  GIMSK=0x40; // INT0 Interrupt

  while(rec==0); // Ждать, пока не случится стартовый бит
  MCUCR=0; // INT0 Interrupt
  GIMSK=0; // INT0 Interrupt
  coef=115;
  TIMSK0=0x04;
  TCCR0B=0x02;
  rec=0;
  TCNT0=0xDC;
  for(a=0; a<9; a++){
    while(Rece_bit==0);

    if(bit_is_set(PINB,1)){
      usart_r |=(1<<7);
    } 
    else {
      usart_r &=~(1<<7);
    }
    usart_r=usart_r>>1;
    Rece_bit=0;
  }
}

int main(void)
{
  DDRB&=~(1<<1); //
  DDRB|=(1<<4); //

  asm("sei");
  while(1)
  {
    UART_receiv(); // Сперва принимаем байт
    _delay_ms(10); // Пауза для наглядности
    UART_trans(ADC_READ()); // Отправляем обратно
  }
}
unsigned int ADC_READ(){ // ініціалізуємо АЦП
  ADMUX = 3; // ADC pin
  ADCSRA |= 1<<ADEN;
  ADCSRA |= 1<<ADSC;
  while(!(ADCSRA & (1<<ADIF)));
  ADCSRA |= 1<<ADIF;
  byte low = ADCL;
  byte high = ADCH;
  ADCSRA &= ~(1 << ADEN); // вимикаємо АЦП
  return (high << 8) | low;
} 

 

Всё компилируется, но при подключении к Rx и Tx пишет всякую ерунду типо:





яяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяшяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяюяяяяяяюяяяяяяюяяяяяяюяяяяяяяяяяяяяюяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяшяяяяяяяяяяяяяяяяяяяяяяяяяяяяяшяяяяяяяяяяяяяяяяяяяяяяюяяяяяяяяяяяяяяююююююююююююююююююююююююююююююююююююююююююююююююююююююююююююююююююююююююююююююююююююююююююююююююююююююююююююююююююююююююююююююююююююююююююююююююююююююююююююююююююююююююююююююююююююююююююююююююююююююююююююююяяяяяяяяяяяяяяяяяяяяяяяяяяяяюяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяюяяяяяяяяяяяяяяяяяяяяяяяяяяяшяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяюяяяяяяюяяяяяяюяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяюяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяюяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяряяяяяяяяяяяяяяяяяяяяяяшяяяяяяяяяяяяяяяяяяяяяяяяяяяяяюяяяяяяяяяяяяяяяяяяяяяяяяяяяяяюяяяяяяяяяяяяяяяяяяяяяяяяяяяряяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяряяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяьяяяяяяяяяяяяяяяяяяяяяяяяяяяяяюяяяяяяяяяяяяяяяюяяяяяяшяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяюяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяюяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяюяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяюяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяюяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяюяяяяяяюяяяяяяяяяяяяяяяяяяяяяяяяяяяяяюяяяяяяюяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяьяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяюяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяюяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяьяяяяяяюяяяяяяюяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяюяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяюяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяюяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяряяяяяяяяяяяяяяяяяяяяяяяяяяяяяюяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяюяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяюяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяюяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяюяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяя

Может кто больше знает подскажет можно ли что-то исправить, и как это сделать?

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

Стоит ли создавать новую тему в этом разделе по отпугивателю?

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

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

На видео зашил скетч Debounce из IDE.

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

Схема класика, резистор на ресете 10 кОм, подтягивает его к +,на 0 пине "висит" реле для фар, кнопка подключена к 3-му пину. Я так понимаю тут нужно EEPROM но я ещё никогда с ним не работал, прошу помощи с решением.

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

Ну вот набросал немного на Arduino пока, но почему-то неработает, светодиод постоянно мигает.





#include <EEPROM.h>
int address = 1;
byte value;
const int buttonPin = 2;
const int ledPin =  13; 
int buttonState = 0;  

void setup() {
  pinMode(ledPin, OUTPUT);      
  pinMode(buttonPin, INPUT); 
}

void loop() {
  value = EEPROM.read(address); 
  if (value == 1) // считаем EEPROM, если 1 то вкл лампу, 0 - выкл.
  {       
    digitalWrite(ledPin, HIGH);  
  } 
  else 
  {
    digitalWrite(ledPin, LOW); 
  }
  
  buttonState = digitalRead(buttonPin);
  if (buttonState == HIGH) 
  {     
    if (value == 1) 
    {       
      EEPROM.write(address, 0);
    } 
    else 
    {
      EEPROM.write(address, 1);
    }
  } 
  delay(500);
}


 

maksim
Offline
Зарегистрирован: 12.02.2012
#include <EEPROM.h>

#define buttonPin  2
#define ledPin    13
#define address    1

bool value = 0, buttonState = 0;

void setup() 
{
  pinMode(ledPin, OUTPUT); 
  value = EEPROM.read(address);
  digitalWrite(ledPin, value);
}

void loop() 
{
  if(digitalRead(buttonPin) && !buttonState) 
  {     
    value = !value;
    EEPROM.write(address, value);
    digitalWrite(ledPin, value);
    buttonState = 1;    
    delay(100);
  } 
  if(!digitalRead(buttonPin) && buttonState) 
  {
    buttonState = 0;    
    delay(50);
  }
}

 

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

Спасибо, работает на тини:

http://www.youtube.com/watch?v=dbsgm2SHg-4

Я так понимаю с этого момента отсчёт пошёл на 100 000 нажатий?

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

Незнаю как с микроконтроллерами, а с флешками дела хуже, не доживают они до своих 100 000.

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

Вот ещё вопрос, всегда было интересно, если скажем я захочу зашить прошивку в HEX формате при помощи стороннего программатора, скажем USBASP или "Программатором Громова" то какие фюзы нужно мне будет выставить для тини13 чтобы зашить HEX файл который сгенерировала ARDUINO IDE ?

 

 

leshak
Offline
Зарегистрирован: 29.09.2011

HWman пишет:

 

Вот ещё вопрос, всегда было интересно, если скажем я захочу зашить прошивку в HEX формате при помощи стороннего программатора, скажем USBASP или "Программатором Громова" то какие фюзы нужно мне будет выставить для тини13 чтобы зашить HEX файл который сгенерировала ARDUINO IDE ?

Фьюзы - можете подсмотреть в файле Boards.txt для своей платы.

А можете проще. Пойти в File/Preferences 

И поставить галочку "Show verboase output during [] Compilation". Тогда внизу в окошке будет видно как и с какими параметрами ArduinoIDE вызывает avrdude для заливки. Можете это "подсмотреть скопировать" и пользоватся уже без ArduinoIDE.

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

Спасибо ещё раз.

leshak
Offline
Зарегистрирован: 29.09.2011

HWman пишет:

Спасибо ещё раз.

Ой... а я вас обманул. Нужно галочку ставить не возле Compilation (тогда вы будете видеть "как скомпилировать без ArduinoIDE"), а возле Upload - тогда будет виден вызов дудки (как заливать).

Или ставте обе. Тогда будуте "видеть все". В том числе и где сам .hex взять. Что-бы заливать его в будущем.

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

Открыв boards.txt я обнаружил там следующие строчки:

attiny13.name=ATtiny13 @ 9.6MHz (interne 9.6 MHz clock)
attiny13.upload.using=arduino:arduinoisp
attiny13.bootloader.low_fuses=0x7a
attiny13.bootloader.high_fuses=0xff
attiny13.upload.maximum_size=1024
attiny13.build.mcu=attiny13
attiny13.build.f_cpu=1200000
attiny13.build.core=core13

 

Погуглил и попал на калькулятор фюзов и ввёл low_fuses и high_fuses и получил:

Тоесть когда я буду кому-то давать прошивку в НЕХ формате которую я вынул из временой папки IDE, то чтобы тот человек з с правильным программатором, не дуинкой, верно запрограммировал тиньку ему нужно выставить такие галочки, я всё верно понял?

И ещё вопрос по включении нагрузки одной кнопкой:

Итак, кнопка схематически выглядит вот так:

Нужно чтоды светодиоды светились(подключены к 12 В), подсветка кнопки и индикация роботы дальних фар, тоже питается от 12 В.

Схема того что я вчера напаял выглядит вот так:

Итак, как я понял мне нужно резистор который "прижимал" кнопку к земле перепаять на + и изменить в коде buttonState = 1; тогда получится я как бы инвертирую вход, если кнопку что на первом рисунке нажать то порт микроконтроллера "прижимается" к земле.

Я всё верно понимаю? Я так решу данную задачу?

maksim
Offline
Зарегистрирован: 12.02.2012

С фьзами все верно. А с кодом нет - нужно из 26 строки восклицательный знак перед digitalRead перенести  в 18 строку, а резистор можно вообще убрать и включить внутреннюю подтяжку.

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

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

 

Кстати, я тут пиркупил солнечную панельку на 20 ватт, вот и думаю сделать контроллер на тиньке, как в народе говорят PWM типа, тоесть уменьшать ток зарядки при помощи ШИМ на 12/24 В с автоопределением, стоит ли создавать отдельную тему по нему в разделе проекты? 

Хоть и мой алгоритм заряда довольно примитивен но тут как мне кажется всё будет путаться...

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

Интересно интересно...

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

Вот такой код работает как надо:

#include <EEPROM.h>

#define buttonPin  3
#define ledPin    0
#define address    0

bool value = 0, buttonState = 0;

void setup() 
{
  pinMode(buttonPin, INPUT);
  pinMode(ledPin, OUTPUT); 
  value = EEPROM.read(address);
  digitalWrite(ledPin, value);
}

void loop() 
{
 digitalWrite(buttonPin, HIGH);
  if(!digitalRead(buttonPin) && !buttonState) 
  {     
    value = !value;
    EEPROM.write(address, value);
    digitalWrite(ledPin, value);
    buttonState = 1;    
    delay(100);
  } 
  if(digitalRead(buttonPin) && buttonState) 
  {
    buttonState = 0;    
    delay(50);
  }
}

 

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

Думаю имеет место быть.

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

Или Вы это предусмотрели? Смотрю в протеусе записывает один раз когда кнопка нажата, держи сколько влезет, индикатор записи в епром негорит.

Вы уж меня простите, если что.

 

maksim
Offline
Зарегистрирован: 12.02.2012

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

#include <EEPROM.h>

#define buttonPin  3
#define ledPin    0
#define address    0

bool value = 0, buttonState = 0;

void setup() 
{
  digitalWrite(buttonPin, HIGH);
  pinMode(ledPin, OUTPUT); 
  value = EEPROM.read(address);
  digitalWrite(ledPin, value);
}

void loop() 
{
  if(!digitalRead(buttonPin) && !buttonState) 
  {     
    value = !value;
    EEPROM.write(address, value);
    digitalWrite(ledPin, value);
    buttonState = 1;    
    delay(100);
  } 
  if(digitalRead(buttonPin) && buttonState) 
  {
    buttonState = 0;    
    delay(50);
  }
}

Вы чуть-чуть вникните в код и посмотрите сколько раз происходит запись в ЕЕПРОМ пока кнопка удерживается. А что бы вникнуть ознакомьтесь: Работа с кнопками. В помощь новичку.

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

подскажите пожалуйста по пинам на тиньке. не понял какие пины чему соответствуют

нашел только 

вывод 1 - это pin 5

вывод 2 - это pin 3

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

вопрос снимается

вроде нашел решение. не проверял еще работает или нет. указывать напрямую выводы проще

int duration;

void setup()
{
  pinMode(PB5, INPUT);  
  pinMode(PB0, OUTPUT);
}

void loop()

{
  duration = 10;
  digitalWrite(PB0, LOW);
  if (duration < 1500)
  {
    digitalWrite(PB0, HIGH);
  }
}

и нашел еще такую картинку

//                 +-\/-+

// ADC0 (D 5) PB5 1|    |8 Vcc

// ADC3 (D 3) PB3 2|    |7 PB2 (D 2) ADC1

// ADC2 (D 4) PB4 3|    |6 PB1 (D 1) PWM1

//            GND 4|    |5 PB0 (D 0) PWM0

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

PB5 это ресет, использовать его неполучится если фюзы не сменить, кстати, у меня получается использовато только ногу PB3 в качестве АЦП, другие почуму-то нехотят.