Raspberry Piで7seg LEDダイナミック点灯

4桁の7seg LEDをラズパイにGPIO経由で接続して、時刻(mm:ss)を表示させてみた。


1桁の7segを表示する場合、ドットを含めて8個のGPIOを使う。
なので、単純に4桁の7segを表示するには、4*8=32個のGPIOが必要になるが、
ダイナミック点灯方式なるものを使えば、4+8=12個のGPIOで済むのでこれを採用。
実際には1桁ずつしか同時には点灯していないが、高速で順番に4桁を点灯させていくので
人の目には4桁が同時に点灯しているように見えるということらしい。

プログラム的には上記の仕組みをそのまま実装すれば実現できた。
ただ、シェルスクリプトの実装(echo)だと処理が遅すぎてあからさまにチカチカしてしまうので、
Luaのio.openなどを使用して書き直したらまぁまぁスムーズになったのでよしとする。


以下はLuaのコード(print_date.lua)

  1 #!/usr/bin/lua
  2
  3 local keta={}
  4 keta[4]='/sys/class/gpio/gpio2/value'
  5 keta[3]='/sys/class/gpio/gpio3/value'
  6 keta[2]='/sys/class/gpio/gpio7/value'
  7 keta[1]='/sys/class/gpio/gpio8/value'
  8
  9 local leds={}
 10 leds['a']='/sys/class/gpio/gpio11/value'
 11 leds['b']='/sys/class/gpio/gpio10/value'
 12 leds['c']='/sys/class/gpio/gpio24/value'
 13 leds['d']='/sys/class/gpio/gpio27/value'
 14 leds['e']='/sys/class/gpio/gpio22/value'
 15 leds['f']='/sys/class/gpio/gpio9/value'
 16 leds['g']='/sys/class/gpio/gpio23/value'
 17 leds['p']='/sys/class/gpio/gpio25/value'
 18
 19 local f={}
 20
 21 local LED_ON=0
 22 local LED_OFF=1
 23
 24 function setup_gpio(path)
 25   local gpio_num = string.match(path, '%d+')
 26   os.execute('echo '..gpio_num..' > /sys/class/gpio/export')
 27   os.execute('echo out > /sys/class/gpio/gpio'..gpio_num..'/direction')
 28 end
 29
 30 function close_gpio(path)
 31   local gpio_num = string.match(path, '%d+')
 32   os.execute('echo '..gpio_num..' > /sys/class/gpio/unexport')
 33 end
 34
 35 function clear_all_leds()
 36   f['a']:write(LED_OFF); f['b']:write(LED_OFF); f['c']:write(LED_OFF); f['d']:write(LED_OFF);
 37   f['a']:flush();        f['b']:flush();        f['c']:flush();        f['d']:flush();
 38   f['e']:write(LED_OFF); f['f']:write(LED_OFF); f['g']:write(LED_OFF); f['p']:write(LED_OFF);
 39   f['e']:flush();        f['f']:flush();        f['g']:flush();        f['p']:flush();
 40 end
 41
 42 function print_number(num)
 43   if num == 0 then
 44     f['a']:write(LED_ON); f['b']:write(LED_ON); f['c']:write(LED_ON); f['d']:write(LED_ON); f['e']:write(LED_ON); f['f']:write(LED_ON);
 45     f['a']:flush();       f['b']:flush();       f['c']:flush();       f['d']:flush();       f['e']:flush();       f['f']:flush();
 46   elseif num == 1 then
 47     f['b']:write(LED_ON); f['c']:write(LED_ON);
 48     f['b']:flush();       f['c']:flush();
 49   elseif num == 2 then
 50     f['a']:write(LED_ON); f['b']:write(LED_ON); f['d']:write(LED_ON); f['e']:write(LED_ON); f['g']:write(LED_ON);
 51     f['a']:flush();       f['b']:flush();       f['d']:flush();       f['e']:flush();       f['g']:flush();
 52   elseif num == 3 then
 53     f['a']:write(LED_ON); f['b']:write(LED_ON); f['c']:write(LED_ON); f['d']:write(LED_ON); f['g']:write(LED_ON);
 54     f['a']:flush();       f['b']:flush();       f['c']:flush();       f['d']:flush();       f['g']:flush();
 55   elseif num == 4 then
 56     f['b']:write(LED_ON); f['c']:write(LED_ON); f['f']:write(LED_ON); f['g']:write(LED_ON);
 57     f['b']:flush();       f['c']:flush();       f['f']:flush();       f['g']:flush();
 58   elseif num == 5 then
 59     f['a']:write(LED_ON); f['c']:write(LED_ON); f['d']:write(LED_ON); f['f']:write(LED_ON); f['g']:write(LED_ON);
 60     f['a']:flush();       f['c']:flush();       f['d']:flush();       f['f']:flush();       f['g']:flush();
 61   elseif num == 6 then
 62     f['a']:write(LED_ON); f['c']:write(LED_ON); f['d']:write(LED_ON); f['e']:write(LED_ON); f['f']:write(LED_ON); f['g']:write(LED_ON);
 63     f['a']:flush();       f['c']:flush();       f['d']:flush();       f['e']:flush();       f['f']:flush();       f['g']:flush();
 64   elseif num == 7 then
 65     f['a']:write(LED_ON); f['b']:write(LED_ON); f['c']:write(LED_ON); f['f']:write(LED_ON);
 66     f['a']:flush();       f['b']:flush();       f['c']:flush();       f['f']:flush();
 67   elseif num == 8 then
 68     f['a']:write(LED_ON); f['b']:write(LED_ON); f['c']:write(LED_ON); f['d']:write(LED_ON); f['e']:write(LED_ON); f['f']:write(LED_ON); f['g']:write(LED_ON);
 69     f['a']:flush();       f['b']:flush();       f['c']:flush();       f['d']:flush();       f['e']:flush();       f['f']:flush();       f['g']:flush();
 70   elseif num == 9 then
 71     f['a']:write(LED_ON); f['b']:write(LED_ON); f['c']:write(LED_ON); f['d']:write(LED_ON); f['f']:write(LED_ON); f['g']:write(LED_ON);
 72     f['a']:flush();       f['b']:flush();       f['c']:flush();       f['d']:flush();       f['f']:flush();       f['g']:flush();
 73   end
 74 end
 75
 76 function get_time()
 77   time = os.date("%T")
 78   local min={}
 79   local sec={}
 80   min[1] = tonumber(string.sub(time, 4, 4))
 81   min[2] = tonumber(string.sub(time, 5, 5))
 82   sec[1] = tonumber(string.sub(time, 7, 7))
 83   sec[2] = tonumber(string.sub(time, 8, 8))
 84   return min, sec
 85 end
 86
 87 for i,v in pairs(leds) do setup_gpio(v); f[i] = io.open(v, 'w') end
 88 for i,v in pairs(keta) do setup_gpio(v) end
 89
 90 local f1 = io.open(keta[1], 'w')
 91 local f2 = io.open(keta[2], 'w')
 92 local f3 = io.open(keta[3], 'w')
 93 local f4 = io.open(keta[4], 'w')
 94
 95 clear_all_leds()
 96
 97 -- while true do
 98 for i=1,10000 do
 99   local min, sec = get_time()
100
101   f1:write(1)
102   f1:flush()
103   print_number(min[1])
104 --  os.execute('sleep 0.001')
105   clear_all_leds()
106   f1:write(0)
107   f1:flush()
108
109   f2:write(1)
110   f2:flush()
111   print_number(min[2])
112   f['p']:write(LED_ON)
113   f['p']:flush()
114 --  os.execute('sleep 0.001')
115   clear_all_leds()
116   f2:write(0)
117   f2:flush()
118
119   f3:write(1)
120   f3:flush()
121   print_number(sec[1])
122 --  os.execute('sleep 0.001')
123   clear_all_leds()
124   f3:write(0)
125   f3:flush()
126
127   f4:write(1)
128   f4:flush()
129   print_number(sec[2])
130 --  os.execute('sleep 0.001')
131   clear_all_leds()
132   f4:write(0)
133   f4:flush()
134 end
135
136 for i,v in pairs(leds) do close_gpio(v); f[i]:close() end
137 for i,v in pairs(keta) do close_gpio(v) end
138
139 f1:close()
140 f2:close()
141 f3:close()
142 f4:close()
最終更新:2015年12月03日 23:31
添付ファイル