Advertisement
Antyos

Rotary Encoder - ATTiny85 I2C Slave

Jul 31st, 2018
439
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.51 KB | None | 0 0
  1. /*  ===  ROTARY ENCODER I2C SLAVE  ===
  2.  *    Program takes input from a rotary encoder on a AtTiny85 and
  3.  *    sends the position and button data back via IĀ²C upon request
  4.  *
  5.  *  Code and Library borrowed from: https://github.com/lucullusTheOnly/TinyWire
  6.  *
  7.  *  KY-040 Rotary Encoder: http://henrysbench.capnfatz.com/henrys-bench/arduino-sensors-and-input/keyes-ky-040-arduino-rotary-encoder-user-manual/
  8.  *
  9.  *  Transmit byte:
  10.  *     1 0100000
  11.  *     ^ \_____/
  12.  *     |    ^-- Offset from 63
  13.  *     |
  14.  *     |---- Is the button pressed? (0: No, 1: Yes)
  15.  *
  16.  *  =====  PINOUT  ======
  17.  *
  18.  *  Rotary Encoder:                AtTiny85:
  19.  *   - CLK  (Pin 1)                  _____
  20.  *   - DT   (Pin 2)              5 -|O    |-    +5v
  21.  *   - SW   (Switch)         DT  3 -|     |- 2  SCL
  22.  *   - +    (+5v)           CLK  4 -|     |- 1  SW
  23.  *   - GND  (Ground)        GND    -|_____|- 0  SDA
  24.  *
  25.  */
  26.  
  27. #include <TinyWire.h>
  28.  
  29. // Size of one edge of the matrix
  30. #define I2C_SLAVE_ADDRESS 0x6
  31.  
  32. // Rotary encoder pins
  33. #define PIN_1 4
  34. #define PIN_2 3
  35. #define SWITCH_PIN 1
  36.  
  37. const byte buttonBit = B10000000;   // the bit the button is stored on to transmit
  38. const int defPos = 63;              // The default encoder position
  39. volatile int8_t encoderOffset = 0;  // The offset from the default position
  40. boolean pressed = false;            // Is the button pressed?
  41.  
  42. int pinALast;
  43. int aVal;
  44.  
  45. const byte def_tx = B00111111;   // Default transmit byte
  46. byte i2c_tx = def_tx;            // Byte for transmitting data
  47.  
  48.  
  49. //===================================================================
  50. //    CUSTOM FUNCTIONS
  51. //===================================================================
  52.  
  53. //*******************************************************************
  54. // Gets the displacement of the rotary encoder
  55. // Code based on: http://henrysbench.capnfatz.com/henrys-bench/arduino-sensors-and-input/keyes-ky-040-arduino-rotary-encoder-user-manual/
  56. void readRotaryEncoder() {
  57.   aVal = digitalRead(PIN_1);
  58.  
  59.   if (aVal != pinALast) { // Means the knob is rotating
  60.     // if the knob is rotating, we need to determine direction
  61.     // We do that by reading pin B.
  62.     if (digitalRead(PIN_2) != aVal) {  // Means pin A Changed first - We're Rotating Clockwise
  63.       encoderOffset ++;
  64.       //value++;
  65.     }
  66.     else { // Otherwise B changed first and we're moving CCW
  67.       encoderOffset--;
  68.       //value--;
  69.     }
  70.   }
  71.  
  72.   pinALast = aVal;
  73. }
  74.  
  75.  
  76. //*******************************************************************
  77. // Returns if the switch is pressed or not
  78. boolean getSwitchState(){
  79.   return !digitalRead(SWITCH_PIN);
  80. }
  81.  
  82.  
  83. //*******************************************************************
  84. // Make the byte to transmit
  85. byte getTransmitByte() {
  86.   byte b = 0; // byte to return
  87.   int pos = defPos + encoderOffset;   // get the position of the encoder relative to the center
  88.   pos = constrain(pos, 0, 127); // make sure that the position is between 0 to 127
  89.  
  90.   b = pos; // set the byte to the offset from 64
  91.  
  92.   // if the button is pressed
  93.   if (pressed) b |= buttonBit; // set the buttonBit on
  94.   else b &= ~buttonBit; // set the buttonBit off
  95.  
  96.   return b; // return the byte to be transmitted
  97.  
  98. }
  99.  
  100.  
  101. //===================================================================
  102. //    MAIN FUNCTIONS
  103. //===================================================================
  104.  
  105. void setup() {
  106.   // set pinsto input for rotary encoder
  107.   pinMode(PIN_1, INPUT);
  108.   pinMode(PIN_2, INPUT);
  109.   pinMode(SWITCH_PIN, INPUT_PULLUP);
  110.  
  111.   // config TinyWire library for I2C slave functionality
  112.   TinyWire.begin(I2C_SLAVE_ADDRESS);
  113.   // register a handler function in case of a request from a master
  114.   TinyWire.onRequest(onI2CRequest);
  115.  
  116.   pinALast = digitalRead(PIN_1);
  117. }
  118.  
  119.  
  120. void loop() {
  121.   // Update the offset
  122.   readRotaryEncoder();
  123.  
  124.   // Get if the button is pressed or not
  125.   pressed = getSwitchState();
  126.  
  127.   // Update the I2C transfer buffer
  128.   i2c_tx = getTransmitByte();
  129.  
  130. }
  131.  
  132. //*******************************************************************
  133. // Request Event handler function
  134. //  --> Keep in mind, that this is executed in an interrupt service routine. It shouldn't take long to execute
  135. // Based on code from: https://github.com/lucullusTheOnly/TinyWire/blob/master/examples/slave_sender/slave_sender.ino
  136. void onI2CRequest() {
  137.   // sends one byte 'i2c_tx' to the master containing encoder offset and button state
  138.   TinyWire.send(i2c_tx);
  139.  
  140.   // clear the transmit byte
  141.   i2c_tx = def_tx;
  142.  
  143.   //reset the encoder offset
  144.   encoderOffset = 0;
  145. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement