Datasheet attiny25/v, attiny45/v, attiny85/v — complete (atmel)

Модельный ряд для этого даташита

ATtiny25

ATtiny25-20MF ATtiny25-20MFR ATtiny25-20MU ATtiny25-20MUR ATtiny25-20PU ATtiny25-20SH ATtiny25-20SHR ATtiny25-20SN ATtiny25-20SNR ATtiny25-20SSH ATtiny25-20SSHR ATtiny25-20SSN ATtiny25-20SSNR ATtiny25-20SSU ATtiny25-20SSUR ATtiny25-20SU ATtiny25-20SUR

ATtiny25V

ATtiny25V-10MF ATtiny25V-10MFR ATtiny25V-10MU ATtiny25V-10MUR ATtiny25V-10PU ATtiny25V-10SH ATtiny25V-10SHR ATtiny25V-10SN ATtiny25V-10SNR ATtiny25V-10SSH ATtiny25V-10SSHR ATtiny25V-10SSN ATtiny25V-10SSNR ATtiny25V-10SSU ATtiny25V-10SSUR ATtiny25V-10SU ATtiny25V-10SUR

ATtiny45

ATtiny45-20MU ATtiny45-20MUR ATtiny45-20PU ATtiny45-20SH ATtiny45-20SHR ATtiny45-20SU ATtiny45-20SUR ATtiny45-20XU ATtiny45-20XUR

ATtiny45V

ATtiny45V-10MU ATtiny45V-10MUR ATtiny45V-10PU ATtiny45V-10SH ATtiny45V-10SHR ATtiny45V-10SU ATtiny45V-10SUR ATtiny45V-10XU ATtiny45V-10XUR

ATtiny85

ATtiny85-20MU ATtiny85-20MUR ATtiny85-20PU ATtiny85-20SH ATtiny85-20SHR ATtiny85-20SU ATtiny85-20SUR

ATtiny85V

ATtiny85V-10MU ATtiny85V-10MUR ATtiny85V-10PU ATtiny85V-10SH ATtiny85V-10SHR ATtiny85V-10SU ATtiny85V-10SUR

Методики отладки

   
Теперь немного расскажу о способах отладки прошивок. Простейший из способов —
моргание светодиодом на выводе p1. Скажем, по умолчанию моргаем 1 раз в секунду,
при условии 2 — 2 раза и т.д. Однако это случай довольно примитвный. Мне же довелось
отлаживать проект, использующий ЦАП (ADC), а там уже 1024 значения. Моргать конечно можно,
но как считать :) ? И тут я решил поподробнее изучить шину i2c, она использует 2 провода,
одно устройство — мастер, и куча рабов, до 127. И этот способ мне показался довольно
перспективным. Можно сделать головное устройство на Arduino Mega, и на общую шину посадить не один десяток
устройств, как исполнительных механизмов, так и датчиков.

   
Отладочный скетч для мастера на Arduino Mega. Используется библиотека для работы с i2c wire. В цикле запрашивается
информация с i2c раба с номером 11. Полученную информацию можно выводить в COM-порт, или на экран, подключенный к
мастеру.

#include <Wire.h>

byte GetI2C(byte dev){
  byte ret, ret2;

    ret = Wire.requestFrom(dev, 1, true);
    if( ret == 0 ){
      return 255;
    }

    ret2 = 254;
    while( Wire.available() > 0){
      ret2 = Wire.read();
    }
  return ret2;
}

void setup() {
	Wire.begin();
	
	TWBR = 12; //400 kHz i2c
}

void loop(){
	fromdigispark = GetI2C(11);
}

   
Отладочный скетч для раба Digispark. Поскольку аппаратной поддержки i2c в digispark нет,
для эмуляции i2c используются библиотеки TineWireS и TineWireM для раба и мастера соответственно.
Нужную библиотеку нужно скачать и положить в
папку проекта. Здесь для входа аналогового сигнала используется ADC2, он же p4.

#define I2C_SLAVE_ADDRESS   11
#include "TinyWireS.h"
#ifndef TWI_RX_BUFFER_SIZE
#define TWI_RX_BUFFER_SIZE ( 16 )
#endif

#include <core_adc.h>

void requestEvent(){  
	int adc_val;
  
	ADC_SetInputChannel( (adc_ic_t) 2);
	ADC_StartConversion();
	while( ADC_ConversionInProgress() );
	adc_val = ADC_GetDataRegister();
	adc_val = (adc_val >> 2);
	TinyWireS.send((byte) adc_val);
}

void receiveEvent(uint8_t howMany)
{
	...
}

void setup() {
	pinMode(1, OUTPUT);

	TinyWireS.begin(I2C_SLAVE_ADDRESS);
	TinyWireS.onReceive(receiveEvent);
	TinyWireS.onRequest(requestEvent);

	digitalWrite(3, HIGH);

	pinMode(3, INPUT); //adc
}

void loop() {
	digitalWrite(1, HIGH);
	tws_delay(50);
	digitalWrite(1, LOW);
	tws_delay(1000);

	TinyWireS_stop_check();
}

   
По итогу можно сказать, что преимущества данной платы — возможность использования части библиотек от ардуино,
либо сторонних. В отличие от того же ассемблера. В сравнении с ардуино, digispark раза в полтора дешевле
самой простой arduino nano.

Using the Digispark with the Arduino IDE:

The Digispark works a bit differently than some Arduino compatible products. The Digispark programs with a different procedure.

From the Tools menu select Board→Digispark (Default — 16.5Mhz)

(The Tools→Programmer selection does not matter)

Write some code, open your code, or open a Digispark example.

You do not need to plug in your Digispark before invoking upload

Hit the upload button. The bottom status box will now ask you to plug in your Digispark — at this point you need to plug it in — or unplug and replug it.

You’ll see the upload progress and then it will immediately run your code on the Digispark.

If you unplug the Digispark and plug it back in or attach it to another power source there will be a delay of 5 seconds before the code you programmed will run. This 5 second delay is the Digispark Pro checking to see if you are trying to program it.

О возможностях среды разработки

Arduino IDE имеет встроенный набор плат и микроконтроллеров, с которыми можно работать; в её основе лежит классический программатор AVR, кстати, благодаря ему и можно обращаться к устройству командами на Си.

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

  • сервопривод;
  • транзистор;
  • светодиод;
  • соленоид и т. д.

Поэтому сторонние разработчики создали целый ряд совместимых плат. Работать с ними можно через Arduino IDE, используя простые команды встроенного языка. Для этого были переписаны загрузчики и библиотеки команд.

Step 9: Program MCU

  1. Plug your ISP to the computer
  2. Run Arduino
  3. Open ATtinyWatch.ino from unzipped ATtinyWatch folder
  4. Select Tools menu -> Board sub-menu -> select ATtiny85
  5. Select Tools menu -> Clock sub-menu -> select 1 MHz (internal oscillator; BOD disabled)
  6. Select Tools menu -> Programmer sub-menu -> your ISP
  7. Remove CR1220
  8. Connect the SOIC ISP clip to ATtiny85 and press Upload button

ISP -> ATtiny85

MISO -> Pin 6

VCC -> Pin 8

SCK -> Pin 7

MOSI -> Pin 5

RESET -> Pin 1

GND -> Pin 4

Remark:

If you have SSD1306 screen other than 64×32 resolution, you can change resolution define in ssd1306.h

e.g.

// custom screen resolution by define SCREEN128X64, SCREEN128X32, SCREEN64X48 or SCREED64X32 (default)#define SCREEN_128X64
//#define SCREEN_128X32
//#define SCREEN_64X48 // not tested
//#define SCREEN_64X32

Other program ATtiny85 reference:

Using the Digispark with the Arduino IDE:

The Digispark (and Pro) works a bit differently than some Arduino compatible products. Not only is there a special add-on to the IDE to support it, but it also programs with a different procedure.

From the Tools menu select Board→Digispark Pro (16Mhz) (Default)

(The Tools→Programmer selection does not matter)

Write some code, open your code, or open a Digispark example.

You do not need to plug in your Digispark Pro before invoking upload

Hit the upload button. The bottom status box will now ask you to plug in your Digispark Pro — at this point you need to hit the reset button on it or plug it in.

You’ll see the upload progress and then it will immediately run your code on the Digispark Pro.

If you unplug the Digispark Pro and plug it back in or attach it to another power source there will be a delay of 5 seconds before the code you programmed will run. This 5 second delay is the Digispark Pro checking to see if you are trying to program it. After the 5 second delay when the bootloader launches the stored program, the USB device will typically go away (and may report a failure to install, or “Unknown Device”) unless the nature of the ‘sketch’ is to act as a USB device.

Общее описание

ATtiny25/45/85 — экономичный 8-разр. КМОП микроконтроллеры, выполненные по усовершенствованной AVR RISC-архитектуре. За счет выполнения большинства инструкций за один машинный цикл микроконтроллеры ATtiny25/45/85 достигают производительности 1млн. оп. в сек. при тактировании частотой 1МГц, что позволяет разработчику оптимизировать потребляемую мощность и быстродействие.

Ядро AVR комбинирует богатый набор инструкций с 32 регистрами общего назначения, которые непосредственно подключены к арифметико-логическому устройству (АЛУ). Это позволяет осуществлять доступ при выполнении инструкции сразу к двум регистрам и выполнить ее за один машинный цикл. Результирующая архитектура обладает более высокой эффективностью, обеспечивая производительность в более чем 10 раз выше по сравнению с традиционными CISC-микроконтроллерами.

ATtiny25/45/85 содержит следующие элементы: 2/4/8 кбайт внутрисистемно-программируемой флэш-памяти, 128/256/512 байт ЭСППЗУ, 128/256/256 байт статического ОЗУ, 6 линий ввода-вывода общего назначения, 32 универсальных рабочих регистров общего назначения, один 8-разр. таймер-счетчик с режимами сравнения, один 8-разр. высокоскоростной таймер-счетчик, универсальный последовательный интерфейс, внутренние и внешние прерывания, 4-канальный 10-разр. АЦП, программируемый сторожевой таймер с внутренним генератором, а также три программно выбираемых экономичных режима. В режиме холостого хода (Idle) останавливается ЦПУ при этом продолжают работу статическое ОЗУ, таймер-счетчик, АЦП, аналоговый компаратор и система прерываний. В режиме пониженной мощности (Power-down) сберегается содержимое регистров, отключаются все встроенные функции до следующего прерывания или аппаратного сброса. В режиме снижения шумов АЦП (ADC Noise Reduction) останавливается ЦПУ и все модули ввода-вывода, кроме АЦП, за счет чего достигается снижение цифровых шумов во время преобразования АЦП.

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

Analog Read:

int sensorValue = 0;

void setup() {
    //You need not set pin mode for analogRead - though if you have set the pin to
    //output and later want to read from it then you need to set pinMode(0,INPUT);
    //where 0 is the physical pin number not the analog input number.
    //
    //See below for the proper pinMode statement to go with each analog read.
}

void loop() {
    // The analog pins are referenced by their analog port number, not their pin
    //number and are as follows:

    sensorValue = analogRead(1); //Read P2
    //To set to input: pinMode(2, INPUT);
    //THIS IS P2, P2 is analog input 1, so when you are using analog read, you refer to it as 1.

    //sensorValue = analogRead(2); //Read P4
    //To set to input: pinMode(4, INPUT);
    //THIS IS P4, P4 is analog input 2, so when you are using analog read, you refer to it as 2.

    //sensorValue = analogRead(3); //Read P3
    //To set to input: pinMode(3, INPUT);
    //THIS IS P3, P3 is analog input 3, so when you are using analog read, you refer to it as 3.

    //sensorValue = analogRead(0); //Read P5
    //To set to input: pinMode(5, INPUT);
    //THIS IS P5, P5 is analog input 0, so when you are using analog read, you refer to it as 0.
}

Differences (from the Arduino) and limitations

The Digispark is compatible with the Arduino IDE — that does not, however, mean it can do everything an Arduino can do. In order to achieve the low cost and small size of the Digispark some compromises had to be made.

Here is a list of some of the differences worth considering when designing or troubleshooting (pin differences are outlined in the sections below this list):

  1. The Digispark only has about 6 KB of flash memory for storing your code.
  2. Pin 3 and Pin 4 (P3 and P4) are used for USB communication and programming, while you can use them in your circuit if you are not using USB communication, you may have to unplug your circuit during programming if the circuit would impede the pin states or dramatically affect the voltage levels on these pins.
  3. Pin 3 (P3) has a 1.5 kΩ pull-up resistor attached to it which is required for when P3 and P4 are used for USB communication (including programming). Your design may need to take into account that you’d have to overpower this to pull this pin low.
  4. The Digispark does not have a hardware serial port nor a hardware serial to USB converter. An example library (DigiUSB) is provided, as well as some example code and a serial monitor like program, but communication with the computer will not always be plug and play, especially when other libraries are involved.

Digital Read:

NOTE: The internal pull-up resistor (turned on by calling digitalWrite(0) after setting the pin to output, where 0 is the pin number) are much weaker (about 25 kohm) on an ATtiny than on an Arduino, so the onboard LED interferes with them. If you need them, you can use a different port. Change your circuit to not need the internal pull-up, or cut the LED trace. For Model A this would apply to P1 for Model B this would apply to P0.(Model Identification)

int sensorValue = 0;

void setup() {
    //All pins are capable of digital input.
    pinMode(0, INPUT); //0 is P0, 1 is P1, 2 is P2, etc. - unlike the analog inputs, for digital inputs the pin number matches.
}

void loop() {
    sensorValue = digitalRead(1); //Returns HIGH or LOW (true or false / 1 or 0).
}

Notes on serial monitoring

ATtiny85 does not provide a native serial interface, but it can be generated via software:

  • bit-bang two-way serial half-duplex (two pins)
  • bit-bang serial-out (one pin)

Both provide a TTL UART hardware interface (using one or two pins different from P3 and P4, used for USB). If the PC has a physical serial port, an external TTL-to-RS232 hardware interface is needed. If USB is required to connect a PC, an external UART-USB hardware converter is needed.

The above described options are ways to monitor a Digispark via Arduino «serial monitor».

Similarly to the UART serial port, USB monitoring can be emulated via a bit-bang software implementation of the Digispark USB interface, emulating a serial port. All these options do not allow monitoring via Arduino «serial monitor».

DKeyboard example:

#define USE_KEYBOARD
#define KEYBOARD_DELAY 1500 // Time to wait for the PC keyboard driver to become ready

#ifdef USE_KEYBOARD
#include "DKeyboard.h" // Use a modified tiny DigisparkKeyboard library
DKeyboardDevice Db = DKeyboardDevice(); // instantiate the Keyboard driver
#endif

void setup() {
...
#ifdef USE_KEYBOARD
    Db.sendKeyStroke();
    Db.delay(KEYBOARD_DELAY); // This is needed to wait for the PC keyboard driver to become ready
    Db.sendKeyStroke(); // This will ensure no character will be lost
#endif
...
}

void loop() {
...
#ifdef USE_KEYBOARD
    Db.print("Value result is ");
    Db.println(value);
    Db.print("Hex value is ");
    Db.println(hexvalue, HEX);
    Db.delay(300); // ensure that the transmission is performed before the interrupt is turned off
#endif
...
}

Steps to use DKeyboard for debug log monitoring:

  • Create a new folder called DKeyboard under the folder named «libraries» in your Arduino sketchbook folder. Create the folder «libraries» in case it does not exist yet. Copy all the files under libraries/DKeyboard to the target «DKeyboard» subfolder. This is a modified version of DKeyboard that slightly reduces its size so that it can be loaded to the Digispark ATTINY85 device. ATtiny85 presents itself to the PC as a keyboard USB HID.
  • Connect the Digispark to the PC via USB
  • Immediately after the code is successfully uploaded, remove the Digispark USB from the PC (to prevent interference of the emulated keyboard)
  • Open a Notepad and put the Windows focus there (maximizing the Notepad window is also suggested to prevent accidentally losing the focus)
  • Insert the USB to the PC (do not move the focus out of the Notepad window until the USB is connected)

False errors of missing USB driver messages can occur with Windows (should be ignored). If no data is shown, increase KEYBOARD_DELAY timer.

The following DKeyboard Hello World code takes 2784 bytes (42% of the available rooms):

#define KEYBOARD_DELAY 1500

#include "DKeyboard.h"
DKeyboardDevice Db = DKeyboardDevice();

void setup() {
  Db.sendKeyStroke();
  Db.delay(KEYBOARD_DELAY);
  Db.sendKeyStroke();
}

void loop() {
  Db.println("Hello World");
  Db.delay(300);
}

DKeyboard needs timer interrupt disabled. If timer interrupt is used (e.g, IRMP or IRemote, interrupts shall be temporarily disabled.

Hardware PWM

To use hardware PWM in your sketch, use the function.

In the default implementation of PWM in arduino IDE, hardware PWM frequency is quite low:

Digispark @ 16.5MHz
Digispark Pin PWM Frequency (Hz)
Pin0 504
Pin1 504
Pin4 1007

By setting FAVOR_PHASE_CORRECT_PWM to 0 in arduino-1.0x/hardware/digispark/cores/tiny/core_build_options.h file, it’s possible to double the frequency on Pin1:

Digispark @ 16.5MHz
+ FAVOR_PHASE_CORRECT_PWM set to 0
Digispark Pin PWM Frequency (Hz)
Pin0 504
Pin1 1007
Pin4 1007

But for some applications, this may be not sufficient. For example, if the Digispark is used as Electronic Speed Controller for brushed motors, using hardware PWM which such a low frequency is not perfect: the ESC will be noisy (audible) since PWM frequency is within the audio range.

Another application where “high” frequency is required: Digital Analog Converter. Using a PWM pin followed with a simple RC low pass filter, it’s very easy to build a DAC. Using a high PWM frequency will increase the response time and will reduce the ripple.

How to increase Hardware PWM Frequency?

The usual way to increase PWM frequency consists in changing the assigned timer prescaler. This is not sufficient: micros(), millis() and delay() will be broken since these functions rely on the timer which is also used for PWM.

New Digispark IDE release (may 2013) introduces a new capability: Hardware PWM frequency adjustment without breaking micros(), millis() and delay().

Simply by setting the new MS_TIMER_TICK_EVERY_X_CYCLES symbol in arduino-1.0x/hardware/digispark/cores/tiny/wiring.c file to a value lower than 64 (the default arduino value), it’s possible to increase the hardware PWM frequency.

The maximum reachable frequency for Pin1 and Pin4 is obtained with:

  • The maximum Digispark clock frequency: 16.5MHz
  • FAVOR_PHASE_CORRECT_PWM set to 0
  • MS_TIMER_TICK_EVERY_X_CYCLES set to 1
Digispark @ 16.5MHz
+ FAVOR_PHASE_CORRECT_PWM set to 0
+ MS_TIMER_TICK_EVERY_X_CYCLES set to 1
Digispark Pin PWM Frequency (Hz)
Pin0 32227
Pin1 64453
Pin4 64453

Note: Frequencies for other MS_TIMER_TICK_EVERY_X_CYCLES values are easy to compute:
Take the above frequency values and divide them with MS_TIMER_TICK_EVERY_X_CYCLES.

For example, if MS_TIMER_TICK_EVERY_X_CYCLES is set to 8, the obtained frequencies are 8 time smaller.

loop() is invoked each time

Variables defined in loop() get reinitialized every time… there is no magic goto the top. So:

void loop () {
  // don't use this buggy code!
  int second; // first bug here! (see explanation below)
  second = second + 1;
 
  if (second = 15) { // second bug here! (see explanation above)
     // this code runs every loop, because second is set to 15, and 15 is non-zero, so is truthy.
     // effectively the same as writing:
     // second = 15;
     // if (15 != 0) {
     //   ...
     // }
  }
  delay(1000);
}

If you really want something to run once 15 seconds after you power it up, you need something more like

void loop () {
  // use "static" to remember this value from one loop to the next.
  // Also, initialize it to something reasonable.
  static int seconds = ;
 
  if ( 15 == seconds ) { // use the correct "==" for comparison.
     // this code runs only the 15th time through the loop.
     Serial.write("hey, it's been 15 seconds!");
  }
  delay(1000);
  seconds = seconds + 1;
}

Even the above code has a minor bug – the Arduino Uno uses 16 bits in the “int”, so a “seconds” count stored in an “int” rolls over.
So it prints the message once 15 seconds after power-up, as desired, and then prints it out again (!) roughly every 18 hours.

Self-Programming the Attiny – or the digispark way of life

To enable that feature you need to use one of the other two methods mentioned before to get a piece of code on the attiny. This will then allow you to pull additional code into the attiny or change the additional code. Uploading that initial code is one of the tasks in the digispark-production.

This bootloader resides in the first 2k of the 8k memory of the attiny and allows you to use the remaining 6k for your programs. The big benefit of that piece of smart code is that you need no other hardware tool to program a digispark as you would for the other two methods. It will even go one step further and make it possible for you to use the digispark for programming other core attinys in two (or lets say one and a half) different ways.

For that purpose micronucleus emulates USB hardware as the attiny has no on-board USB device. Communication is done with a host component called micronucleus. On Windows systems it’s micronucleus.exe.

To facilitate this special way of programming the digispark, digistump has patched the IDE by adding a custom version of avrdude (a program which is mostly used in the arduino world). Digistump’s custom version of avrdude is a wrapper which calls either the original avrdude for everything which is not a digispark, or micronucleus in the case of a digispark.
There are however some drawbacks:

The emulation of a USB interface affects the usage of 2 I/O pins, P3 (analog3) and P4 (analog2). Both are regulated with a Zener diode which limits the voltage on those two pins to a max of 3.6V. This affects some uses like analogRead() or high levels resulting from digitalWrite(). P3 also has a 1.5K pullup-resistor creating even more problems for this kind of usage.

An advantage of the emulated USB solution is that this way of programming the Attiny frees one more GPIO pin; pin PB5. This pin is otherwise used as reset, which is needed for programming the chip with an external ISP programmer.

Small Introduction to pin-names

You need to be very careful, when it comes to PIN names on the AVR microcontrollers. There are plenty of names around depending on functions or locations. Further enumeration depends, if that is done logical or physical.

There are the pin numbers of the core chip, starting with one at the special marked pin going counter-clockwise around the chip. Then there are the numbers of GPIO-pins which AVR groups to internal ports, where up to 8 pins can be aggregated. Those ports are named with letters (A, B, ..). Unfortunately the attiny85 is missing port A, so the GPIO pins are called PB0 to PB5. And as you see, in the logical enumeration they start with 0 and there is no match to the physical pin number. When it comes down to the digispark itself, those 6 pins are named P0 to P5 on the PCB; however in the schematics enumeration starts with 1.

There are a lot of other names, depending of functions for special protocols or chip-functions, like SCK, MISO, MOSI. Those additional functions are even not related to corresponding GPIO-pins. On the attiny85 SCK is together with PB2 on physical pin7. On the attiny167, for example, SCK resides with PA5 on physical pin 8. So always pay attention to documentation before making assumptions!

Its not much more to say, about the internal programming, as that is the out-of-the box behaviour.

Step 2: Setup Arduino With ATtiny85, EEPROM and TinyWireM Support

Download

Download Arduino 1.6.5 (1.6.6/7 have known compatible issue — «contains deprecated recipe.ar.pattern»)

Download ArduinoTiny (if you not familiar with GitHub, simply click Download ZIP button)

Locate the Arduino path

If you install with Windows install, it should be:

C:\Program Files\Arduino

If you are using OSX, it should be:

/Applications/Arduino.app/Contents/Java

Or any path you unzipped to.

Add EEPROM support

In Arduino path, copy hardware\arduino\avr\libraries\EEPROM\EEPROM.h to hardware\tiny\avr\cores\tiny folder.

Install TinyWireM Library

  1. Run Arduino
  2. Select Sketch Menu -> Include Library sub-menu -> Manage Libraries…
  3. Search TinyWireM
  4. Select TinyWireM and click Install button
  5. Close Library Manager and close Arduino

Debug TinyWireM

  1. Locate TinyWireM library path (Windows: «My Documents\Arduino\libraries\TinyWireM»; OSX: «~/Documents/Arduino/libraries/TinyWireM»)
  2. Modify «TinyWireM.cpp» line 53, save and close the file

from:

if (USI_BufIdx >= USI_BUF_SIZE) return 0;       // dont blow out the buffer

To:

if (USI_BufIdx >= USI_BUF_SIZE - 1) return 0;       // dont blow out the buffer
Оцените статью:
Оставить комментарий
Adblock
detector