残像映出機の制作

回転の残像で映像を表示するものを作りました。

構造としては、ホールセンサーで回転位置を特定して、rpmを求め、割り込みを作り、74hc595で拡張したIOから、LEDをON,OFFして、画像を表示します。

 

プログラムとしては

sekiei7_degree90_video1flame

#include <MsTimer2.h>
#include <TimerOne.h>
#include <avr/pgmspace.h>
#include"data.h"
/*5-
 * ->SER
   6-->RCLK
   7-->SRCLK
   3-->HIGH(SUPPLYホール素子)
   4-->ホール素子出力
*/
#define holl 3
#define hollsupply 4
#define ser 5
#define rclk 6
#define srclk 7
void fullsend(byte far, byte midfar, byte midclose, byte veryclose);
//volatile boolean key = 0;
volatile int count ;
volatile int phaze = 0;
/*
   0->初期、20回平均出す
   1->タイマ割り込みにより出力
   2->1周にかかる時間を計算する事でタイマ割り込みを更新する(ある一定以下もう一度行う)f
     l   1に戻る
*/

/*
   data[x][0],data[x][1],data[x][2],data[x][3]
   veryclose ,midclose  ,midfar    ,far


*/
//30周に一回割り込みの時間を変更する
volatile unsigned long time1a;
volatile unsigned long time2a;
volatile unsigned long rpsa;
volatile int phaze1firstkey = 0;
volatile int videoPoint;
volatile int videoCount;

volatile int rollpoint = 0; //90個に分割して出力する
void Hollkey() {
  count++;
  rollpoint = 0;
}
void counter() {
  //画像の出力
  if (rollpoint <= 89) {
    int k1=pgm_read_word_near(&data[rollpoint][3]);
    int k2=pgm_read_word_near(&data[rollpoint][2]);
    int k3=pgm_read_word_near(&data[rollpoint][1]);
    int k4=pgm_read_word_near(&data[rollpoint][0]);
    fullsend(k1,k2,k3,k4);

    rollpoint++;
  }else{
    fullsend(0xff,0xff,0xff,0xff);
    
  }
}

void setup() {
  
  pinMode(hollsupply, OUTPUT);
  digitalWrite(hollsupply, HIGH);
  pinMode(holl, INPUT);
  pinMode(ser, OUTPUT);
  pinMode(rclk, OUTPUT);
  pinMode(srclk, OUTPUT);
  for (int i = 0; i < 10; i++) {
    fullsend(0x00, 0x00, 0x00, 0x00);
  }
  count = 0;
  videoCount=0;
  videoPoint=0;
  attachInterrupt(1, Hollkey, RISING);
  Serial.begin(9600);
}


void loop() {
  time1a = micros();

  while (count < 1) { } count = 0; time2a = micros(); rpsa = (time2a - time1a) ; videoCount++; if(videoCount>=40){
    videoPoint++;
    if(videoPoint==60){
      videoPoint=0;
    }
  }
  if (rpsa > 5000) { //5ms以下は却下

    Timer1.initialize(rpsa / 90);//1*90
    Timer1.start();
    Timer1.attachInterrupt(counter);
  }
}

void show() {
  digitalWrite(rclk, HIGH);
  digitalWrite(rclk, LOW);
}
void senddata(int data) {
  if (data == 0) {
    digitalWrite(ser, LOW);
    digitalWrite(srclk, HIGH);
    digitalWrite(srclk, LOW);

  } else {
    digitalWrite(ser, HIGH);
    digitalWrite(srclk, HIGH);
    digitalWrite(srclk, LOW);
    /*
      digitalWrite(rclk, HIGH);
      digitalWrite(rclk, LOW);
    */
  }
}
void databytesend(byte x) {
  byte y;
  for (int i = 0; i <= 7; i++) { byte xy = x >> i;
    y = xy & 0x01;
    //Serial.println(y);
    if (y == 1) {
      senddata(1);
    } else {
      senddata(0);
    }
  }
}
void fullsend(byte far, byte midfar, byte midclose, byte veryclose) {
  databytesend(veryclose);
  databytesend(midclose);
  databytesend(midfar);
  databytesend(far);
  show();
}


設計をFusion360で作り、CNCと3Dプリンタで実際に制作しました。


回転部分に電池をつけないために、土台と回転部分に鉄球をつけることで電源を供給しました。
一番苦労したのは回転部分の重心位置を真ん中に持ってくることです。最終的には、結構振動が残りましたが、あきらめました。
mdfの扱いや3dCADなど、craneさんから教えてもらいました。外装を結構凝って作ったのが面白かったです。


2017/10/31 製作者 hiRo