LoginSignup
2
0

More than 5 years have passed since last update.

汎用LED MATRIX DISPLAYを、ラズパイで使ってみる5

Last updated at Posted at 2017-12-09

さて。
Raspberry Piに、登録していきましょうかね。

まず今回は、ファイル使うので。
SDカードへの負担を減らすため、RAMディスクを登録。

root@raspberrypi:/# mkdir /ramdisk
root@raspberrypi:/# chmod -R 777 /ramdisk
root@raspberrypi:/# cat /etc/fstab
proc            /proc           proc    defaults          0       0
PARTUUID=1bee5e28-01  /boot           vfat    defaults          0       2
PARTUUID=1bee5e28-02  /               ext4    defaults,noatime  0       1
# a swapfile is not a swap partition, no line here
#   use  dphys-swapfile swap[on|off]  for that
tmpfs           /ramdisk        tmpfs   defaults,size=16m 0 0

root@raspberrypi:/#

ま、マウント用ディレクトリ作って、fstabに登録、mount-aか再起動でRAMディスクが16MBできますよ、と。

で、出力はbmp、入力はppmなので、image-magickをセットアップ

root@raspberrypi:/# apt-get install imagemagick

LEDに表示する画像を作製するスクリプトと、LEDに画像を表示するスクリプトを、サービスとして作製。

root@raspberrypi:/# cd /etc/systemd/system
root@raspberrypi:/etc/systemd/system# cat makeledinfo.service
[Unit]
Description = makeledinfo

[Service]
ExecStart=/usr/bin/perl /data/ledinfo/makeledinfo.pl
Restart=always
Type=simple

[Install]
WantedBy=multi-user.target

root@raspberrypi:/etc/systemd/system# cat ledimageloader.service
[Unit]
Description = ledimageloader

[Service]
ExecStart=/usr/bin/python /data/ledinfo/ledimageloader.py -r 32 -c 2 -b 30 --led-slowdown-gpio 2 -p 5
Restart=always
Type=simple

[Install]
WantedBy=multi-user.target
root@raspberrypi:/etc/systemd/system#

systemctlで登録、と。
もう動かしてるので、ステータスで!。

root@raspberrypi:/etc/systemd/system# systemctl status makeledinfo.service
● makeledinfo.service - makeledinfo
   Loaded: loaded (/etc/systemd/system/makeledinfo.service; enabled; vendor preset: enabled)
   Active: active (running) since Sun 2017-11-26 19:57:04 JST; 1 weeks 5 days ago
 Main PID: 7990 (perl)
   CGroup: /system.slice/makeledinfo.service
           tq 7990 /usr/bin/perl /data/ledinfo/makeledinfo.pl
           mq30184 /usr/bin/python /data/ledinfo/hummeas.py

Warning: Journal has been rotated since unit was started. Log output is incomplete or unavailable.
root@raspberrypi:/etc/systemd/system# systemctl status ledimageloader.service
● ledimageloader.service - ledimageloader
   Loaded: loaded (/etc/systemd/system/ledimageloader.service; enabled; vendor preset: enabled)
   Active: active (running) since Sat 2017-12-09 11:55:01 JST; 45min ago
 Main PID: 26104 (python)
   CGroup: /system.slice/ledimageloader.service
           mq26104 /usr/bin/python /data/ledinfo/ledimageloader.py -r 32 -c 2 -b 30 --led-slowdown-gpio 2 -p 5

12月 09 11:55:01 raspberrypi systemd[1]: Started ledimageloader.
root@raspberrypi:/etc/systemd/system#

数日動かしっぱなしにしてると、なんか盛大にハングしたので、たまにサービス再起動を仕込みました。

root@raspberrypi:/# cd /etc
root@raspberrypi:/etc# cat crontab
# /etc/crontab: system-wide crontab
# Unlike any other crontab you don't have to run the `crontab'
# command to install the new version when you edit this file
# and files in /etc/cron.d. These files also have username fields,
# that none of the other crontabs do.

SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

# m h dom mon dow user  command
17 *    * * *   root    cd / && run-parts --report /etc/cron.hourly
25 6    * * *   root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )
47 6    * * 7   root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )
52 6    1 * *   root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )
#

55 * * * * root /usr/sbin/service ledimageloader restart
root@raspberrypi:/etc#

ま、これで、無事?動作。

動画だと、こんな感じです。
https://twitter.com/eucalydqx/status/934809174143221761

なかなか視認性も良く、取り扱いしやすいブツに仕上がり、まんぞくまんぞく。

最後に、実際に登録している、perlスクリプト、置いておきます。
/data/ledinfo とか、/ramdisk とかがキーワードかな。
あと、温度計計測用のスクリプトも、ここからキックしてますー。

makeledinfo.pl
$inputbitmapfontfilename = "/data/ledinfo/bfont.bmp";
$inputbitmapbackgroundfilename = "/data/ledinfo/back.bmp";
$humdatafilename2 = "/ramdisk/humoutput1.txt";
$humdatafilename1 = "/ramdisk/humoutput2.txt";
$outputfilename = "/ramdisk/ledoutput.bmp";

&inputbitmapfont;

while (){
 &meashum;
 &makeinfo;
 &imageconvert;
 sleep(2);
}
exit;

sub meashum {
 $systemcommand = "/usr/bin/python /data/ledinfo/hummeas.py";
 system ($systemcommand);
 $systemcommand = "/usr/bin/python /data/ledinfo/hummeas2.py";
 system ($systemcommand);
}

sub imageconvert {
 $systemcommand = "/usr/bin/convert /ramdisk/ledoutput.bmp /ramdisk/ledoutput.ppm";
 system ($systemcommand);
}

sub makeinfo{
 open (FILE,$humdatafilename1);
 (@humdataarray) = (<FILE>);
 close (FILE);

 chomp($humdataarray[0]);
 if ($humdataarray[0] < 0){
  $j = abs(int ($humdataarray[0]));
  $k = abs(int ($humdataarray[0] * 10));
  $k = $k - ($j * 10);
  $j = sprintf("%03d",$j);
  $k = sprintf("%01d",$k);
  $output_it = "-$j.$k";
 }
 else {
  $j = abs(int ($humdataarray[0]));
  $k = abs(int ($humdataarray[0] * 100));
  $k = $k - ($j * 100);
  $j = sprintf("%02d",$j);
  $k = sprintf("%02d",$k);
  $output_it = "$j.$k";
 }
 chomp($humdataarray[1]);
 $j = abs(int ($humdataarray[1] / 100));
 $k = abs(int ($humdataarray[1]));
 $k = $k - ($j * 100);
 $j = sprintf("%04d",$j);
 $k = sprintf("%02d",$k);
 $output_ip = "$j.$k";
 chomp($humdataarray[2]);
 $j = abs(int ($humdataarray[2]));
 $k = abs(int ($humdataarray[2] * 100));
 $k = $k - ($j * 100);
 $j = sprintf("%02d",$j);
 $k = sprintf("%02d",$k);
 $output_ih = "$j.$k";

 open (FILE,$humdatafilename2);
 (@humdataarray) = (<FILE>);
 close (FILE);

 chomp($humdataarray[0]);
 if ($humdataarray[0] < 0){
  $j = abs(int ($humdataarray[0]));
  $k = abs(int ($humdataarray[0] * 10));
  $k = $k - ($j * 10);
  $j = sprintf("%03d",$j);
  $k = sprintf("%01d",$k);
  $output_ot = "-$j.$k";
 }
 else {
  $j = abs(int ($humdataarray[0]));
  $k = abs(int ($humdataarray[0] * 100));
  $k = $k - ($j * 100);
  $j = sprintf("%02d",$j);
  $k = sprintf("%02d",$k);
  $output_ot = "$j.$k";
 }
 chomp($humdataarray[1]);
 $j = abs(int ($humdataarray[1] / 100));
 $k = abs(int ($humdataarray[1]));
 $k = $k - ($j * 100);
 $j = sprintf("%04d",$j);
 $k = sprintf("%02d",$k);
 $output_op = "$j.$k";
 chomp($humdataarray[2]);
 $j = abs(int ($humdataarray[2]));
 $k = abs(int ($humdataarray[2] * 100));
 $k = $k - ($j * 100);
 $j = sprintf("%02d",$j);
 $k = sprintf("%02d",$k);
 $output_oh = "$j.$k";


 #tokoyami
 $timenow = time;
 $timeseed = $timenow - 1510434000;
 $timeseed = int ($timeseed / 86400);
 $timeseed %= 4;

 if ($timeseed == 0){($toko_r,$toko_d,$toko_m) = (1,3,2);}
 if ($timeseed == 1){($toko_r,$toko_d,$toko_m) = (2,4,3);}
 if ($timeseed == 2){($toko_r,$toko_d,$toko_m) = (3,1,4);}
 if ($timeseed == 3){($toko_r,$toko_d,$toko_m) = (4,2,1);}

 #boueigun
 $timenow = time;
 $timeseed = $timenow - 1510434000;
 $timeseed = int ($timeseed / 3600);
 $timeseed %= 7;

 if ($timeseed == 0){($defe_i,$defe_j) = ("Yy","Yy");}
 if ($timeseed == 1){($defe_i,$defe_j) = ("Yy","Ww");}
 if ($timeseed == 2){($defe_i,$defe_j) = ("Ww","Ww");}
 if ($timeseed == 3){($defe_i,$defe_j) = ("Ww","Xx");}
 if ($timeseed == 4){($defe_i,$defe_j) = ("Xx","Xx");}
 if ($timeseed == 5){($defe_i,$defe_j) = ("Xx","Zz");}
 if ($timeseed == 6){($defe_i,$defe_j) = ("Zz","Yy");}

 (@date) = localtime (time);
 $time_format = sprintf("%02d:%02d",$date[2],$date[1]);

 $dataone = "  " .$output_it."c  ".$output_ot."c";
 $datatwo = "  " .$output_ih."p  ".$output_oh."p";
 $datathr = $output_ip."h".$output_op."h";
 $datafou = "R".$toko_r."D".$toko_d."M".$toko_m." ".$defe_i.$defe_j.$time_format;

 #print "$dataone\n$datatwo\n$datathr\n$datafou\n";
 &inputbasebitmap;
 $outputline = 0;$outputcol = 0;
 foreach $ch (split //, $dataone) { &renderfont($ch);$outputcol++;}
 $outputline = 1;$outputcol = 0;
 foreach $ch (split //, $datatwo) { &renderfont($ch);$outputcol++;}
 $outputline = 2;$outputcol = 0;
 foreach $ch (split //, $datathr) { &renderfont($ch);$outputcol++;}
 $outputline = 3;$outputcol = 0;
 foreach $ch (split //, $datafou) { &renderfont($ch);$outputcol++;}

 $bitmapoutput = "424d361800000000000036000000280000004000000020000000010018000000000000180000120b0000120b00000000000000000000";
 for $i (0..31){
  for $j (0..63){
   for $k (0..2){
    $bitmappointer = (( 31 - $i ) * 64 + $j) * 3 + $k;
    $bitmapoutput .= $bitmapoutputbase[$bitmappointer];
   }
  }
 }
 $bitmapbinary = pack("H*",$bitmapoutput);
 open (OUTPUT,">$outputfilename");
 binmode(OUTPUT);
 print OUTPUT $bitmapbinary;
 close (OUTPUT);
}

sub inputbitmapfont {
 open (IN,$inputbitmapfontfilename);
 binmode (IN);

 $buffersize = 1;
 $count = 0;
 $output = "";
 undef (@rawdata);
 $rawcount = 0;
 while (){
  $count++;
  read(IN,$readdata,$buffersize);
  if ($count < 55){next;}
  if ($count > 20000){last;}
  $readdata = unpack("H2",$readdata);
  $rawdata[$rawcount] = $readdata;
  $rawcount++;
 }
 close (IN);

#      コゥ・    E       コヨAア・ゥ鈬ノ
                                  ?B

 for ($i=1;$i>-1;$i--){
  for ($j=0;$j<16;$j++){
   $fontseed = "$i:$j";
   for ($k=7;$k>-1;$k--){
    for ($l=0;$l<4;$l++){
     $imagex = (( $j * 4 ) + $l) * 3;
     $imagey = ( $i * 8 ) + $k;
     $imagepointerbase = ( $imagey * 64 * 3 ) + $imagex;
     for ($m=0;$m<3;$m++){
      $imagepointer = $imagepointerbase + $m;
      $fontdata{$fontseed} .= $rawdata[$imagepointer];
     }
    }
   }
  }
 }
}

sub inputbasebitmap {
 open (IN,$inputbitmapbackgroundfilename);
 binmode (IN);

 $buffersize = 1;
 $count = 0;
 $output = "";
 undef (@bitmapoutputbase);
 $colcount = 0;
 $rowcount = 31;
 while (){
  $count++;
  read(IN,$readdata,$buffersize);
  if ($count < 55){next;}
  if ($count > 20000){last;}
  $readdata = unpack("H2",$readdata);
  $rawcount = $rowcount * 64 * 3;
  $rawcount += $colcount;
  $bitmapoutputbase[$rawcount] = $readdata;
  $colcount++;
  if ($colcount > 191){
   $rowcount--;
   if ($rowcount < 0){last;}
   $colcount = 0;
  }
 }
 close (IN);
}


sub renderfont {
 my $data = $_[0];

#0123456789.ch:p-
#RDMぶけラ
 $fontseed = "1:15";
 if ($data eq " "){$fontseed = "1:15";}
 if ($data eq "0"){$fontseed = "0:0";}
 if ($data eq "1"){$fontseed = "0:1";}
 if ($data eq "2"){$fontseed = "0:2";}
 if ($data eq "3"){$fontseed = "0:3";}
 if ($data eq "4"){$fontseed = "0:4";}
 if ($data eq "5"){$fontseed = "0:5";}
 if ($data eq "6"){$fontseed = "0:6";}
 if ($data eq "7"){$fontseed = "0:7";}
 if ($data eq "8"){$fontseed = "0:8";}
 if ($data eq "9"){$fontseed = "0:9";}
 if ($data eq "."){$fontseed = "0:10";}
 if ($data eq "c"){$fontseed = "0:11";}
 if ($data eq "h"){$fontseed = "0:12";}
 if ($data eq ":"){$fontseed = "0:13";}
 if ($data eq "p"){$fontseed = "0:14";}
 if ($data eq "-"){$fontseed = "0:15";}
 if ($data eq "R"){$fontseed = "1:0";}
 if ($data eq "D"){$fontseed = "1:1";}
 if ($data eq "M"){$fontseed = "1:2";}
 if ($data eq "W"){$fontseed = "1:3";}
 if ($data eq "w"){$fontseed = "1:4";}
 if ($data eq "X"){$fontseed = "1:5";}
 if ($data eq "x"){$fontseed = "1:6";}
 if ($data eq "Y"){$fontseed = "1:7";}
 if ($data eq "y"){$fontseed = "1:8";}
 if ($data eq "Z"){$fontseed = "1:9";}
 if ($data eq "z"){$fontseed = "1:10";}
 $fontcolcount = 0;
 $fontrowcount = 0;
 @fontdataarray = $fontdata{$fontseed} =~ /.{2}/g;
 foreach $ch (@fontdataarray) {
  $fontrow = ($outputline * 8) + $fontrowcount;
  $fontcol = ($outputcol * 4 * 3 ) + $fontcolcount;
  $injectpointer = ($fontrow * 3  * 64) + $fontcol;
  if ($ch ne "00"){
   $bitmapoutputbase[$injectpointer] = $ch;
  }
  $fontcolcount++;
  if ($fontcolcount > 11){
   $fontrowcount++;
   $fontcolcount = 0;
  }
 }
}
2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0