Project:Arduino Rotary Encoder Menu System: Difference between revisions
Created page with "I have recovered a number of ALPS rotary encoders from discarded industrial CRT monitors. I'm working on building a user interface menu system that makes use of the rotary encode..." |
m Fowkc moved page Arduino Rotary Encoder Menu System to Project:Arduino Rotary Encoder Menu System |
||
(5 intermediate revisions by one other user not shown) | |||
Line 1: | Line 1: | ||
I have recovered a number of ALPS rotary encoders from discarded industrial CRT monitors. I'm working on building a user interface menu system that makes use of the rotary encoders as the sole input technique. | I have recovered a number of ALPS rotary encoders from discarded industrial CRT monitors. I'm working on building a user interface menu system that makes use of the rotary encoders as the sole input technique. | ||
<div style ="height: | <div style ="height:300px;overflow-x:hidden;overflow-y:auto;border: 4px solid green;"> | ||
'''Rotary Encoder Test Sketch With Interrupts (non-PWM)''' | '''Rotary Encoder Test Sketch With Interrupts (non-PWM)''' | ||
<syntaxhighlight lang="cpp" line="GESHI_FANCY_LINE_NUMBERS" enclose="div"> | <syntaxhighlight lang="cpp" line="GESHI_FANCY_LINE_NUMBERS" enclose="div"> | ||
Line 102: | Line 102: | ||
Serial.println("Encoder Menu - blah, blah, blah"); | Serial.println("Encoder Menu - blah, blah, blah"); | ||
} | } | ||
</syntaxhighlight> | |||
</div> | |||
== multiple encoders == | |||
Try out http://code.google.com/p/adaencoder/ and PinChangeInt library (http://code.google.com/p/arduino-pinchangeint/) see... | |||
http://arduino.cc/playground/Main/RotaryEncoders#Example14 | |||
See if it can cope with two encoders at rapid rate usage. | |||
OK, working well --[[User:Msemtd|Michael Erskine]] 18:10, 29 July 2012 (EST) | |||
== Raspberry Pi menu for rotary encoder == | |||
When using the Raspberry Pi as the menu display system we need to do a few things to a stock raspbian install... | |||
* auto login and start X: use option in raspi-config | |||
* switch off screen blanking: /etc/lightdm/lightdm.conf in SeatDefaults section "xserver-command=X -s 0 -dpms" | |||
* auto start application | |||
Here I'm building a Perl Tk menu application prototype using Tk::Canvas. I haven't yet wired up the serial as I'm just trying out some graphic styles on the small PAL LCD screen. | |||
<div style ="height:300px;overflow-x:hidden;overflow-y:auto;border: 4px solid green;"> | |||
'''Raspberry Pi menu for rotary encoder''' | |||
<syntaxhighlight lang="perl" line="GESHI_FANCY_LINE_NUMBERS" enclose="div"> | |||
#!/usr/bin/perl -w | |||
use strict; | |||
use IO::Handle; | |||
autoflush STDOUT 1; | |||
autoflush STDERR 1; | |||
use tmstub; | |||
use Tk; | |||
#use Tk::FontDialog; | |||
my $title = 'piduino menu'; | |||
my $version = "v0.2 2012-07-29"; | |||
my $mw = new MainWindow(); | |||
# PAL resolution 656x512@16 | |||
$mw->overrideredirect(1); | |||
my ($scr_w, $scr_h) = $mw->maxsize(); | |||
t "maxsize says: $scr_w x $scr_h"; | |||
#~ $mw->geometry("656x512+0+0"); | |||
$mw->geometry("680x540+0+0"); | |||
#~ $mw->FullScreen; | |||
#~ $mw->geometry(($mw->maxsize())[0] .'x'.($mw->maxsize())[1] . "+0+0"); | |||
my $c = $mw->Canvas(-bg => "yellow", -width => 680, -height => 540)->pack; | |||
# in theory we should be able to scroll infinitely but let's stick to something reasonable | |||
#$c->configure(-scrollregion => [0,0, 600, 400]); | |||
my $font = $mw->fontCreate('menufont', -family => 'Village', -size => 38, -weight=>'bold'); | |||
my $menu_w = 400; | |||
my $menu_h = 100; | |||
# it don't work! | |||
#~ invisible_cursor(); | |||
# warp pointer tests... | |||
$mw->after(100, sub {warp(20,20)}); | |||
sub warp { | |||
my($x, $y) = @_; | |||
t "warp pointer to $x $y"; | |||
$c->focus; | |||
$mw->eventGenerate("<Motion>", | |||
-when => 'head', | |||
-x => $x, -y => $y, -warp => 1 | |||
); | |||
} | |||
# keybinding tests... | |||
$mw->bind('<KeyPress>' => \&print_keysym); | |||
sub print_keysym { | |||
my($widget) = @_; | |||
my $e = $widget->XEvent; # get event object | |||
my($keysym_text, $keysym_decimal) = ($e->K, $e->N); | |||
print "keysym=$keysym_text, numeric=$keysym_decimal\n"; | |||
} | |||
# hide cursor | |||
sub invisible_cursor { | |||
my $bitmapfile = Tk->findINC('trans_cur.xbm'); | |||
my $maskfile = Tk->findINC('trans_cur.mask'); | |||
$mw->configure(-cursor => [ '@' . $bitmapfile, $maskfile, 'black', 'white' ] ); | |||
} | |||
# handy font chooser | |||
#~ $mw->Button( | |||
#~ -font => $font, | |||
#~ -text => "Font", | |||
#~ -command => sub{choose_font()}, | |||
#~ )->pack(); | |||
# debug grid... | |||
$c->createGrid(0, 0, 10, 10); | |||
$c->createGrid(0, 0, 50, 50, -lines => 1, -dash => '-.'); | |||
$c->createGrid(0, 0, 100, 100, -width => 3, -lines => 1); | |||
# TODO - load settings from file | |||
menubox("Music", 0, 0); | |||
menubox("Controls", 0, 1); | |||
menubox("Vehicle", 0, 2); | |||
menubox("System", 0, 3); | |||
menubox("Settings", 0, 3); | |||
# menubox("More...", 1, 0); | |||
#~ music selection | |||
#~ playlists | |||
#~ artists by name | |||
#~ albums | |||
#~ directories | |||
#~ controls | |||
#~ volume | |||
#~ bass | |||
#~ treble | |||
#~ balance | |||
#~ system reboot | |||
#~ system shutdown | |||
#~ app quit | |||
#~ app restart | |||
sub menubox { | |||
my($t, $mx, $my) = @_; | |||
my $x1 = $mx * $menu_w; | |||
my $y1 = $my * $menu_h; | |||
my $x2 = $x1 + $menu_w; | |||
my $y2 = $y1 + $menu_h; | |||
$c->createRectangle($x1, $y1, $x2, $y2, | |||
-fill => "blue", | |||
-activefill => "green", | |||
-outline => "green", | |||
-activeoutline => "orange", | |||
); | |||
$c->createText($x1 + ($menu_w/2), $y1+ ($menu_h/2), | |||
-text => "$t", | |||
-font => $font, | |||
-fill => "black", | |||
); | |||
} | |||
=for docs | |||
options: | |||
* canvas width and height to cover the whole menu system | |||
* sub-menus can't all be visible simultaneously so we'd have to hide them | |||
* group items together | |||
do top level menu first | |||
menu level zero at 0,0 | |||
menu level one appears at 1*menu_w, selected item * menu_h | |||
=cut | |||
sub choose_font | |||
{ | |||
# t $mw->GetDescriptiveFontName($font); | |||
# my $f = $mw->FontDialog->Show( | |||
#-initfont => $font, | |||
#-nicefont => 1 | |||
# ); | |||
# return unless defined $f; | |||
# $mw->RefontTree(-font => $f, -canvas => 1); | |||
# my $d = $mw->GetDescriptiveFontName($f); | |||
# t $d; | |||
# $font = $f; | |||
} | |||
MainLoop(); | |||
</syntaxhighlight> | |||
</div> | |||
OK, using adaencoder on the Pi-arduino bridge! The Arduino is just saying what it sees over serial. | |||
<div style ="height:300px;overflow-x:hidden;overflow-y:auto;border: 4px solid green;"> | |||
'''Raspberry Pi menu for rotary encoder''' | |||
<syntaxhighlight lang="cpp" line="GESHI_FANCY_LINE_NUMBERS" enclose="div"> | |||
#include <PinChangeInt.h> // necessary otherwise we get undefined reference errors. | |||
#include <AdaEncoder.h> | |||
#define a_PINA 10 | |||
#define a_PINB 11 | |||
#define BTN 9 | |||
#define LED 13 | |||
#define b_PINA A3 | |||
#define b_PINB A4 | |||
int8_t clicks=0; | |||
char id=0; | |||
void setup() | |||
{ | |||
Serial.begin(9600); | |||
Serial.println("---------------------------------------"); | |||
pinMode(BTN, INPUT); | |||
pinMode(LED, OUTPUT); | |||
digitalWrite(BTN, HIGH); | |||
AdaEncoder::addEncoder('a', a_PINA, a_PINB); | |||
// AdaEncoder::addEncoder('b', b_PINA, b_PINB); | |||
} | |||
void loop() | |||
{ | |||
static unsigned long btnHeld = 0; | |||
encoder *thisEncoder; | |||
thisEncoder=AdaEncoder::genie(&clicks, &id); | |||
if (thisEncoder != NULL) { | |||
thisEncoder=AdaEncoder::getFirstEncoder(); | |||
Serial.print(id); | |||
Serial.print(':'); | |||
Serial.print(clicks, DEC); | |||
if (clicks > 0) { | |||
Serial.println(" UP"); | |||
} | |||
if (clicks < 0) { | |||
Serial.println(" DOWN"); | |||
} | |||
} | |||
// Upon button press... | |||
if((digitalRead(BTN) == LOW) && !btnHeld){ | |||
btnHeld = millis(); | |||
digitalWrite(LED, HIGH); | |||
Serial.println("pressed"); | |||
} | |||
// Upon button release... | |||
if((digitalRead(BTN) == HIGH) && btnHeld){ | |||
long t = millis(); | |||
digitalWrite(LED, LOW); | |||
Serial.print("released: (after "); | |||
t -= btnHeld; | |||
Serial.print(t, DEC); | |||
Serial.println(" ms)"); | |||
btnHeld = 0; | |||
} | |||
} | |||
</syntaxhighlight> | </syntaxhighlight> | ||
</div> | </div> |
Latest revision as of 00:51, 12 June 2014
I have recovered a number of ALPS rotary encoders from discarded industrial CRT monitors. I'm working on building a user interface menu system that makes use of the rotary encoders as the sole input technique.
multiple encoders
Try out http://code.google.com/p/adaencoder/ and PinChangeInt library (http://code.google.com/p/arduino-pinchangeint/) see...
http://arduino.cc/playground/Main/RotaryEncoders#Example14
See if it can cope with two encoders at rapid rate usage.
OK, working well --Michael Erskine 18:10, 29 July 2012 (EST)
When using the Raspberry Pi as the menu display system we need to do a few things to a stock raspbian install...
- auto login and start X: use option in raspi-config
- switch off screen blanking: /etc/lightdm/lightdm.conf in SeatDefaults section "xserver-command=X -s 0 -dpms"
- auto start application
Here I'm building a Perl Tk menu application prototype using Tk::Canvas. I haven't yet wired up the serial as I'm just trying out some graphic styles on the small PAL LCD screen.
OK, using adaencoder on the Pi-arduino bridge! The Arduino is just saying what it sees over serial.