Editor Version ×
recommended

Pro Edition

free

Brand new interactions and interfaces

Smooth support for design sizes of over 3W

devices or 10W pads

More rigorous design constraints, more

standardized processes

For enterprises, more professional users

Std Edition

Easy to use and quick to get started

The process supports design scales of 300

devices or 1000 pads

Supports simple circuit simulation

For students, teachers, creators

Ongoing

STD ATtiny412 I2C Rotary Encoder

ATtiny412 I2C Rotary Encoder

Project tags

License

CC-BY-SA 3.0

License: CC-BY-SA 3.0

Mode:

Mode

Editors' pick

Editors' pick

  • 2.4k
  • 0
  • 8
Update time: 2022-08-19 20:21:19
Creation time: 2022-08-02 07:51:03
Description

Description

# Overview Rotary encoders are a nice touch for many projects. However, their control requires some pins, interrupts and debouncing. Thanks to this device, a rotary encoder can be easily controlled via the I²C interface, the built-in ATtiny202/212/402/412 does the rest. By assigning different I²C addresses, it is even possible to daisy-chain several rotary encoders. The device is powered via the I²C connection and operates in the voltage range between 2.7V and 5V. - Firmware (Github): https://github.com/wagiminator/ATtiny412-I2C-Rotary-Encoder ![pic1.jpg](https://raw.githubusercontent.com/wagiminator/ATtiny412-I2C-Rotary-Encoder/main/documentation/I2C_RotaryEncoder_pic1.jpg) # Hardware ![wiring.png](https://raw.githubusercontent.com/wagiminator/ATtiny412-I2C-Rotary-Encoder/main/documentation/I2C_RotaryEncoder_wiring.png) # Software ## Implementation The heart of the firmware is the I²C slave implementation. Since the ATtiny supports this in hardware, things are pretty easy. A simple register array is used to read and write the rotary encoder parameters and states. Data transmission and reception are handled via interrupts. ```c // I2C slave command macros #define I2C_complete() TWI0.SCTRLB = TWI_SCMD_COMPTRANS_gc #define I2C_response() TWI0.SCTRLB = TWI_SCMD_RESPONSE_gc #define I2C_sendACK() TWI0.SCTRLB = TWI_ACKACT_ACK_gc | TWI_SCMD_RESPONSE_gc #define I2C_sendNACK() TWI0.SCTRLB = TWI_ACKACT_NACK_gc | TWI_SCMD_RESPONSE_gc #define I2C_put(x) TWI0.SDATA = (x) #define I2C_get() TWI0.SDATA // I2C slave status macros #define I2C_isAddr() ((TWI0.SSTATUS & TWI_APIF_bm) && (TWI0.SSTATUS & TWI_AP_bm)) #define I2C_isData() (TWI0.SSTATUS & TWI_DIF_bm) #define I2C_isStop() ((TWI0.SSTATUS & TWI_APIF_bm) && (~TWI0.SSTATUS & TWI_AP_bm)) #define I2C_isIn() (~TWI0.SSTATUS & TWI_DIR_bm) #define I2C_isOut() (TWI0.SSTATUS & TWI_DIR_bm) // I2C slave registers uint8_t I2C_REG[10]; // register array uint8_t I2C_REG_ptr; // register pointer volatile uint8_t I2C_REG_changed = 0; // register change flag volatile uint8_t I2C_busy = 0; // I2C busy flag // I2C slave init void I2C_init(void) { TWI0.SADDR = I2C_ADDR = sizeof(I2C_REG)) // increase pointer... I2C_REG_ptr = 0; // ...or wrap around return; // quit ISR } // Stop condition interrupt handler if(I2C_isStop()) { // stop condition? I2C_complete(); // complete transaction I2C_busy = 0; // clear I2C busy flag } } ``` The I²C address of the device can be set in the firmware parameters at the beginning of the code. ```c // Firmware parameters #define I2C_ADDR 0x36 // I2C address of the device ``` ## Compiling and Uploading the Firmware ### If using the Arduino IDE - Open your Arduino IDE. - Make sure you have installed [megaTinyCore](https://github.com/SpenceKonde/megaTinyCore). - Go to **Tools -> Board -> megaTinyCore** and select **ATtiny412/402/212/202**. - Go to **Tools** and choose the following board options: - **Chip:** Choose the chip that is installed on your device - **Clock:** 10 MHz internal - Leave the rest at the default settings. - Connect your programmer to your PC and to the UPDI header on the board. - Go to **Tools -> Programmer** and select your UPDI programmer. - Go to **Tools -> Burn Bootloader** to burn the fuses. - Open the sketch and click **Upload**. ### If using the makefile (Linux/Mac) - Download [AVR 8-bit Toolchain](https://www.microchip.com/mplab/avr-support/avr-and-arm-toolchains-c-compilers) and extract the sub-folders (avr, bin, include, ...) to /software/tools/avr-gcc. To do this, you have to register for free with Microchip on the download site. - Open a terminal. - Navigate to the folder with the makefile and the sketch. - Run `DEVICE=attiny412 PROGRMR=serialupdi PORT=/dev/ttyUSB0 make install` to compile, burn the fuses and upload the firmware (change DEVICE, PROGRMR and PORT accordingly). # Operating Instructions The device has four 16-bit and two 8-bit registers that can be read and written. The 16-bit registers are signed and the least significant byte is always transmitted first. With each access (reading or writing), the registers are always transferred starting with the first in the following order: 1. Encoder wheel value (16-bit) 2. Encoder switch state (8-bit, 0=switch released, 1=switch pressed) 3. Encoder wheel value loop flag (8-bit, 0=do not loop, 1=loop around) 4. Encoder wheel minimum value (16-bit) 5. Encoder wheel maximum value (16-bit) 6. Encoder wheel value change step (16-bit) An example code for controlling the device is attached. It uses the standard Arduino Wire library, so it should run on almost all supported microcontrollers. ```c #include #define encoder_addr 0x36 int16_t value, lastvalue; boolean pressed, lastpressed; void setup() { Serial.begin(9600); Wire.begin(); encoder_set(-50, 50, 1, 0, 0); } void loop() { value = encoder_getValue(); if(value != lastvalue) { Serial.println(value); lastvalue = value; } pressed = encoder_isPressed(); if(pressed != lastpressed) { if(pressed) Serial.println("Switch was pressed"); lastpressed = pressed; } delay(20); } // Set encoder wheel parameters void encoder_set(int16_t rmin, int16_t rmax, int16_t rstep, int16_t rval, uint8_t rloop) { Wire.beginTransmission(encoder_addr); Wire.write((uint8_t)(rval & 0xff)); Wire.write((uint8_t)(rval >> 8)); Wire.write(0); Wire.write(rloop); Wire.write((uint8_t)(rmin & 0xff)); Wire.write((uint8_t)(rmin >> 8)); Wire.write((uint8_t)(rmax & 0xff)); Wire.write((uint8_t)(rmax >> 8)); Wire.write((uint8_t)(rstep & 0xff)); Wire.write((uint8_t)(rstep >> 8)); Wire.endTransmission(); } // Set encoder wheel value void encoder_setValue(int16_t rval) { Wire.beginTransmission(encoder_addr); Wire.write((uint8_t)(rval & 0xff)); Wire.write((uint8_t)(rval >> 8)); Wire.endTransmission(); } // Read encoder wheel value int16_t encoder_getValue() { Wire.requestFrom(encoder_addr, 2); return((uint16_t)Wire.read() | ((uint16_t)Wire.read()
Design Drawing

Design Drawing

schematic diagram
1 /
PCB
1 /
The preview image was not generated, please save it again in the editor.
ID Name Designator Footprint Quantity BOM_Supplier BOM_Supplier Part
1 100n C1 C_0603 1 LCSC C14663
2 10u C2 C_0603 1 LCSC C19702
3 I2C CN1,CN2 QWIIC 2 LCSC C160404
4 I2C J1,J2 210S-4X1/2.54 2 LCSC C124378
5 UPDI J3 210S-3X1/2.54 1 LCSC C49257
6 10k R1,R2 0603 2 LCSC C25804
7 Rotary Encoder SW1 ROTARY_ENCODER 1 LCSC C143789
8 ATTINY412-SSN U1 SOP-8_150MIL 1 LCSC C1338223

Unfold

Project Attachments

Project Attachments

Empty
Project Members

Project Members

Target complaint
Related Projects
Change a batch
Loading...

Comment

Add to album ×

Loading...

reminder ×

Do you need to add this project to the album?

服务时间

周一至周五 9:00~18:00
  • 0755 - 2382 4495
  • 153 6159 2675

服务时间

周一至周五 9:00~18:00
  • 立创EDA微信号

    easyeda

  • QQ交流群

    664186054

  • 立创EDA公众号

    lceda-cn