Difference between revisions of "Project:Arduino Rotary Encoder Menu System"

From Nottinghack Wiki
Jump to navigation Jump to search
Line 115: Line 115:
 
OK, working well --[[User:Msemtd|Michael Erskine]] 18:10, 29 July 2012 (EST)
 
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...
 
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
 
* 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"
 
* switch off screen blanking: /etc/lightdm/lightdm.conf in SeatDefaults section "xserver-command=X -s 0 -dpms"
 
* auto start application
 
* 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(($mw->maxsize())[0] .'x'.($mw->maxsize())[1] . "+0+0");
 +
my $c = $mw->Canvas(-bg => "red", -width => 650, -height => 400)->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;
 +
 +
 +
# 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>
 +
 +
 +
  
 
moving the cursor with Perl Tk
 
moving the cursor with Perl Tk

Revision as of 23:15, 29 July 2012

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.

Rotary Encoder Test Sketch With Interrupts (non-PWM)

 1 #define PIN_ENC1 2
 2 #define PIN_ENC2 3
 3 #define PIN_EBTN 4
 4 #define PIN_LED1 13
 5 static boolean moving=false;
 6 volatile unsigned int encValue = 0;
 7 unsigned int encValueTracking = 1;
 8 boolean enc1 = false;              
 9 boolean enc2 = false;
10 
11 // Here I'm messing around with button press durations - we could go to town here!
12 enum pressDuration { reallyQuickPress, shortPress, normalPress, longPress, veryLongPress };
13 long presses[] = { 40, 150, 300, 800, 1400 };
14 char* pressText[]={"really quick press!", "short press", "normal press", "long press", "very looooooooong press"};
15 
16 void setup() 
17 {
18   pinMode(PIN_ENC1, INPUT); 
19   pinMode(PIN_ENC2, INPUT); 
20   pinMode(PIN_EBTN, INPUT);
21   pinMode(PIN_LED1, OUTPUT);
22   digitalWrite(PIN_ENC1, HIGH);
23   digitalWrite(PIN_ENC2, HIGH);
24   digitalWrite(PIN_EBTN, HIGH);
25   Serial.begin(9600);
26   menuIntro();
27   attachInterrupt(0, intrEncChange1, CHANGE);
28   attachInterrupt(1, intrEncChange2, CHANGE);
29 }
30 
31 void intrEncChange1()
32 {
33   if(moving) 
34     delay(1);
35   if(digitalRead(PIN_ENC1) == enc1)
36     return;
37   enc1 = !enc1;
38   if(enc1 && !enc2) 
39     encValue += 1;
40   moving = false;
41 }
42 
43 void intrEncChange2()
44 {
45   if(moving) 
46     delay(1);
47   if(digitalRead(PIN_ENC2) == enc2)
48     return; 
49   enc2 = !enc2;
50   if(enc2 && !enc1) 
51     encValue -= 1;
52   moving = false;
53 }
54 
55 void loop() 
56 { 
57   static unsigned long btnHeld = 0;
58   moving = true;
59   if(encValueTracking != encValue){
60     Serial.print("encValue: ");
61     Serial.println(encValue, DEC);
62     encValueTracking = encValue;
63   }
64   // Upon button press...
65   if((digitalRead(PIN_EBTN) == LOW) && !btnHeld){
66     btnHeld = millis();
67     digitalWrite(PIN_LED1, HIGH);
68     Serial.print("pressed selecting: ");
69     Serial.println(encValue, DEC);
70   }
71   // Upon button release...
72   if((digitalRead(PIN_EBTN) == HIGH) && btnHeld){
73     long t = millis();
74     t -= btnHeld;
75     digitalWrite(PIN_LED1, LOW);
76     int dur = veryLongPress;
77     for(int i = 0; i<= veryLongPress; i++){
78       if(t > presses[i])
79          continue;
80       dur = i;
81       break;
82     }
83     
84     Serial.print("released selecting: ");
85     Serial.print(encValue, DEC);    
86     Serial.print(" (after ");
87     Serial.print(t, DEC);
88     Serial.print(" ms = ");
89     Serial.print(pressText[dur]);
90     Serial.println(")");
91     btnHeld = 0;
92   }
93 }
94 
95 void menuIntro()
96 {
97   Serial.println("Encoder Menu - blah, blah, blah");
98 }

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)

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.

Raspberry Pi menu for rotary encoder

  1 #!/usr/bin/perl -w
  2 use strict;
  3 use IO::Handle;
  4 autoflush STDOUT 1;
  5 autoflush STDERR 1;
  6 use tmstub;
  7 use Tk;
  8 #use Tk::FontDialog;
  9 my $title = 'piduino menu';
 10 my $version = "v0.2 2012-07-29";
 11 
 12 my $mw = new MainWindow();
 13 # PAL resolution 656x512@16
 14 $mw->overrideredirect(1);
 15 my ($scr_w, $scr_h) = $mw->maxsize();
 16 t "maxsize says: $scr_w x $scr_h";
 17 $mw->geometry("656x512+0+0");
 18 
 19 #~ $mw->geometry(($mw->maxsize())[0] .'x'.($mw->maxsize())[1] . "+0+0");
 20 my $c = $mw->Canvas(-bg => "red", -width => 650, -height => 400)->pack;
 21 # in theory we should be able to scroll infinitely but let's stick to something reasonable
 22 #$c->configure(-scrollregion => [0,0, 600, 400]);
 23 my $font = $mw->fontCreate('menufont', -family => 'Village', -size => 38, -weight=>'bold');
 24 
 25 my $menu_w = 400;
 26 my $menu_h = 100;
 27 
 28 
 29 # handy font chooser
 30 #~ $mw->Button(
 31 	#~ -font => $font, 
 32 	#~ -text => "Font", 
 33 	#~ -command => sub{choose_font()},
 34 #~ )->pack();
 35 
 36 # debug grid...
 37 $c->createGrid(0, 0, 10, 10);
 38 $c->createGrid(0, 0, 50, 50, -lines => 1, -dash => '-.');
 39 $c->createGrid(0, 0, 100, 100, -width => 3, -lines => 1);
 40 
 41 # TODO - load settings from file
 42 menubox("Music", 0, 0);
 43 menubox("Controls", 0, 1);
 44 menubox("Vehicle", 0, 2);
 45 menubox("System", 0, 3);
 46 menubox("Settings", 0, 3);
 47 # menubox("More...", 1, 0);
 48 
 49 #~ music selection
 50 #~ playlists
 51 #~ artists by name
 52 #~ albums
 53 #~ directories
 54 
 55 #~ controls
 56 #~ volume
 57 #~ bass
 58 #~ treble
 59 #~ balance
 60 #~ system reboot
 61 #~ system shutdown
 62 #~ app quit
 63 #~ app restart
 64 
 65 
 66 
 67 sub menubox {
 68 	my($t, $mx, $my) = @_;
 69 	my $x1 = $mx * $menu_w;
 70 	my $y1 = $my * $menu_h;
 71 	my $x2 = $x1 + $menu_w;
 72 	my $y2 = $y1 + $menu_h;
 73 
 74 	$c->createRectangle($x1, $y1, $x2, $y2, 
 75 		-fill => "blue", 
 76 		-activefill => "green", 
 77 		-outline => "green", 
 78 		-activeoutline => "orange",
 79 	);
 80 	$c->createText($x1 + ($menu_w/2), $y1+ ($menu_h/2), 
 81 		-text => "$t", 
 82 		-font => $font,
 83 		-fill => "black",
 84 	);
 85 }
 86 
 87 
 88 =for docs
 89 
 90 options: 
 91 
 92 * canvas width and height to cover the whole menu system
 93 * sub-menus can't all be visible simultaneously so we'd have to hide them
 94 * group items together
 95 
 96 do top level menu first
 97 
 98 menu level zero at 0,0
 99 menu level one appears at 1*menu_w, selected item * menu_h
100 
101 
102 
103 =cut
104 
105 
106 
107 
108 sub choose_font
109 {
110 #    t $mw->GetDescriptiveFontName($font);
111     
112  #   my $f = $mw->FontDialog->Show( 
113         #-initfont => $font,
114         #-nicefont => 1
115  #   );
116  #   return unless defined $f;
117  #   $mw->RefontTree(-font => $f, -canvas => 1);
118  #   my $d = $mw->GetDescriptiveFontName($f);
119  #   t $d;
120  #   $font = $f;
121 
122 }
123 
124 
125 MainLoop();



moving the cursor with Perl Tk