Arduino – Rotary Encoder met OLED scherm
Dit project laat zien hoe je een Rotary Encoder kan uitlezen en de waarde op een OLED scherm kan laten weergeven.
Het script maakt gebruik van een interrupt, omdat polling in de loop geen mogelijkheid (tijd) geeft om de arduino andere dingen te laten doen.
Wat heb je nodig?
1) Rotary Encoder
2) OLED SPI display
Sluit de componenten aan op de Arduino UNO zoals hieronder aangegeven:
Script
Commentaarregels zijn toegevoegd aan het script.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
// U8glib Bibliotheek importeren #include "U8glib.h" // U8glib Bibliotheek configureren voor het juiste display U8GLIB_SH1106_128X64 u8g(U8G_I2C_OPT_DEV_0|U8G_I2C_OPT_FAST); // Dev 0, Fast I2C / TWI // Encoder pins configureren. int pinEncA=2; int pinEncB=3; static byte abOud; // Initialiseer status. volatile int teller = 0; // rotatie teller. int teller_oud; // oude rotatie teller. // Waarden voor variabel getal reserveren. enum {BufSize=6}; char tellerStr[BufSize]; void setup() { // Encoder pinnen instellen. pinMode(pinEncA, INPUT); pinMode(pinEncB, INPUT); // Interrupts instellen (pin hoog-laag verandering). // Interrupt 0 = Pin 2 op de Arduino UNO. // Interrupt 1 = Pin 3 op de Arduino UNO. attachInterrupt(0, pinActie, CHANGE); attachInterrupt(1, pinActie, CHANGE); u8g.setFont(u8g_font_5x8); // Lettertype instellen voor u8glib. } void loop() { // IF loop wanneer er aan de encoder is gedraaid. if (teller_oud != teller) { teller_oud = teller; snprintf(tellerStr, BufSize, "%d", teller); // Converteer de "teller" INT naar STR (tbv OLED scherm) // OLED scherm loop. u8g.firstPage(); do { u8g.drawStr(0, 10, "Encoder:"); u8g.drawBox(0, 14, 128, 16); // Teken een witte rechthoek, 0px vanaf links, 14px van boven, 128px breed, 16px hoog. u8g.setColorIndex(0); // zet kleur negatief (pixel uit). u8g.setScale2x2(); // maak het lettertype 2x groter. u8g.drawStr(25, 14, tellerStr); // print "teller" tekst. u8g.undoScale(); // zet het lettertype weer terug. u8g.setColorIndex(1); // zet de kleur positief (pixel aan). } while( u8g.nextPage() ); } // Overige code... } // Wanneer een interrupt heeft plaatsgevonden, lees de input pinnen, bereken nieuwe status, pas de telling aan. void pinActie() { enum { upMask = 0x66, downMask = 0x99 }; byte abNieuw = (digitalRead(pinEncA) << 1) | digitalRead(pinEncB); byte criteria = abNieuw^abOud; if (criteria==1 || criteria==2) { if (upMask & (1 << (2*abOud + abNieuw/2))) teller++; // tel naar boven. else teller--; // tel naar beneden. } abOud = abNieuw; // bewaar nieuwe status. } |
2 Encoders
Je kan 2 encoders gebruiken met de Arduino MEGA omdat deze meerdere interrupts ondersteunt (bron @ arduino.cc)
Wat heb je nodig?
1) 2x Rotary Encoder
2) OLED SPI display
Sluit de componenten aan op de Arduino MEGA zoals hieronder aangegeven:
Script
Commentaarregels zijn toegevoegd aan het script.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
// U8glib Bibliotheek importeren #include "U8glib.h" // U8glib Bibliotheek configureren voor het juiste display U8GLIB_SH1106_128X64 u8g(U8G_I2C_OPT_DEV_0|U8G_I2C_OPT_FAST); // Dev 0, Fast I2C / TWI // Encoder pins configureren. int pinEnc1A=2; int pinEnc1B=3; int pinEnc2A=19; int pinEnc2B=18; static byte abOud; // Initialiseer status. volatile int teller1 = 0; // rotatie teller 1. volatile int teller2 = 0; // rotatie teller 2. int teller1_oud; // oude rotatie teller 1. int teller2_oud; // oude rotatie teller 2. // Waarden voor variabel getal reserveren. enum {BufSize=6}; char teller1Str[BufSize]; char teller2Str[BufSize]; void setup() { // Encoder pinnen instellen. pinMode(pinEnc1A, INPUT); pinMode(pinEnc1B, INPUT); pinMode(pinEnc2A, INPUT); pinMode(pinEnc2B, INPUT); // Interrupts instellen (pin hoog-laag verandering). // Interrupt 0 = Pin 2 op de Arduino MEGA. // Interrupt 1 = Pin 3 op de Arduino MEGA. // Interrupt 4 = Pin 19 op de Arduino MEGA. // Interrupt 5 = Pin 18 op de Arduino MEGA. attachInterrupt(0, pinActie1, CHANGE); // Encoder 1. attachInterrupt(1, pinActie1, CHANGE); // Encoder 1. attachInterrupt(4, pinActie2, CHANGE); // Encoder 2. attachInterrupt(5, pinActie2, CHANGE); // Encoder 2. u8g.setFont(u8g_font_5x8); // Lettertype instellen voor u8glib. } void loop() { // IF loop wanneer er aan een encoder is gedraaid. if ((teller1_oud != teller1) || (teller2_oud != teller2)) { teller1_oud = teller1; teller2_oud = teller2; snprintf(teller1Str, BufSize, "%d", teller1); // Converteer de "teller1" INT naar STR (tbv OLED scherm) snprintf(teller2Str, BufSize, "%d", teller2); // Converteer de "teller2" INT naar STR (tbv OLED scherm) // OLED scherm loop. u8g.firstPage(); do { u8g.drawStr(0, 10, "Encoder 1:"); u8g.drawStr(0, 42, "Encoder 2:"); u8g.drawBox(0, 14, 128, 16); // Teken een witte rechthoek, 0px vanaf links, 14px van boven, 128px breed, 16px hoog. u8g.drawBox(0, 46, 128, 16); // Teken een witte rechthoek, 0px vanaf links, 46px van boven, 128px breed, 16px hoog. u8g.setColorIndex(0); // zet kleur negatief (pixel uit). u8g.setScale2x2(); // maak het lettertype 2x groter. u8g.drawStr(25, 14, teller1Str); // print "teller2" tekst. u8g.drawStr(25, 30, teller2Str); // print "teller2" tekst. u8g.undoScale(); // zet het lettertype weer terug. u8g.setColorIndex(1); // zet de kleur positief (pixel aan). } while( u8g.nextPage() ); } // Overige code... } // Wanneer een interrupt heeft plaatsgevonden, lees de input pinnen, bereken nieuwe status, pas de telling aan. void pinActie1() { enum { upMask = 0x66, downMask = 0x99 }; byte abNieuw = (digitalRead(pinEnc1A) << 1) | digitalRead(pinEnc1B); byte criteria = abNieuw^abOud; if (criteria==1 || criteria==2) { if (upMask & (1 << (2*abOud + abNieuw/2))) teller1--; // tel naar boven. else teller1++; // tel naar beneden. } abOud = abNieuw; // bewaar nieuwe status. } // Wanneer een interrupt heeft plaatsgevonden, lees de input pinnen, bereken nieuwe status, pas de telling aan. void pinActie2() { enum { upMask = 0x66, downMask = 0x99 }; byte abNieuw = (digitalRead(pinEnc2A) << 1) | digitalRead(pinEnc2B); byte criteria = abNieuw^abOud; if (criteria==1 || criteria==2) { if (upMask & (1 << (2*abOud + abNieuw/2))) teller2--; // tel naar boven. else teller2++; // tel naar beneden. } abOud = abNieuw; // bewaar nieuwe status. } |