Montag, 21. Februar 2011

First prototype with 555

Overview Turntable Cinema, Drehkino

Don't miss drehkino.de

Inspired by the Zoetrope I developed the Drehkino or Turntable Cinema. The turntable is rotated by one hand whilst the other hand presses the power button. The pickup contains a reflection sensor made from the light barrier of salvaged parts from an old mouse. The pickup can be lifted to change the discs containig short-movies in endless loops of up to 50 pictures.










Hardware

The electronic is simple and consists of a Schmitt-Trigger Inverter to get nice edges from the phototransistor output. This is passed to a differentiating circuit (composed of C3 and R12, must have shorter tau than 555 time base) and fed to the trigger input of a 555 configured as monostable oscillator with configurable time. For a good stroboscopic effect 1/1000s to 1/2000s is ok. Shorter times make the movies sharper at higher speeds but also darker. The LEDs can cope with the high current pulses of ca. 50mA in that short time, but may burn if the pulses get too long.




Software 

A software section for a 555 project? Yes, to produce the discs. First is to get a nice series of pictures from a movie. I use virtualdub to save image sequences of some movies. Cartoons are often at 15fps so you may only use every second picture of your 25fps or 29.97fps source (Menu Video -> Frame Rate -> click Process every other frame). All images are thrown in one directory and the shell script drehkinodir_2_pdf.sh is called with that dir as argument. It calls gawk to compute rotation angles from the number of pictures, the resize options and the bars for the photocoupler. Finally it creates an ImageMagick ("CONVSCRIPT") script which can be executed afterwards. The output is a pdf file which should be printed without resize options on an A4 printer:

 

Shellscript "drehkinodir_2_pdf.sh":

Sorry, comments are in german. The generated CONVSCRIPT  needs somehow an empty image "leer.bmp". Size does not matter. Create it, or take this one (this does not work, it should be a plain white .bmp 10x10):





#!/bin/sh

####
#
# Selber einstellen

# Inputs
# Dots per Inch
dpi=600

# Linewidth in mm
#
linewidth=0.4

# Äusserer Radius der Bilder in mm (BildRandMm)
# (brm=100 am Rand)
brm=100


#
# Breite der Bilder (max 40mm, danach kommt Markierung)
# wenn 0, dann idealberechnung mit dbmax (s.u.)
db=0



#
# Markerdurchmesser in mm
#
mdia=6


#
# Markerbreite (radial) in mm
#
mbm=10

#
# Marker höhe in mm
#
mhm=2.5

#
# debug Level
#
debug=1

##########################
#
# Defaults
#

PI=3.14159265

# dbmax ist maximale bildbreite in mm aufgrund
# radius + breite der markierung (mbm, rmm)
dbmax=40

# DIN A4 Width mm
a4w=210

# DIN A4 Heigth mm
a4h=297

# Durchmesser in mm
ad=200

# Durchmesser Zentralloch
zd=3

#
# Innerer Radius der Markierung (Äusserer durch mbm vorg.)
#
rmm=50

#
#
#

#
# Wieviel Grad verdeckt der Arm, sodass Bilder gut sichtbar
#

ARMVERDECKUNGSWINKEL=15.1



# convert script
sc=CONVSCRIPT
rm -f $sc
touch $sc
chmod +x $sc

if [ -z $1 ]; then
    echo "Argument: Dir"
    exit 1
fi

if [ -d $1 ]; then
    echo "Gut: $1 ist ein Directory"
else
    echo "Brauche Dir als Argumenr"
    exit 1
fi

OUTPDF=`basename $1`.pdf

echo "Erzeuge $OUTPDF"



#
# Muss noch berechnet werden:
#
imx=704
imy=384








getsize()
{
geom=`identify -verbose $1 | grep Geometry | sed "s/.*: //"`
in_width=`echo $geom | sed "s/x.*//"`
in_height=`echo $geom | sed "s/.*x//" | sed "s/+.*//"`
echo "$1 Input Width: $in_width, Height: $in_height"
}









# Dots per meter
dpm=`echo  | gawk "{printf(\"%.0f\",$dpi/0.0254) }"`

echo "dpi: $dpi, dpm: $dpm"

xpixel=`echo  | gawk "{printf(\"%.0f\",$a4w / 1000 * $dpm ) }"`
ypixel=`echo  | gawk "{printf(\"%.0f\",$a4h / 1000 * $dpm ) }"`

echo "Papier: ($a4w mm x $a4h mm) Portrait@${dpi}dpi: $xpixel x $ypixel pixel²)"

strokewidth=`echo  | gawk "{printf(\"%.0f\",$linewidth * $dpm / 1000) }"`
echo "linewidth $linewidth mm wird zu strokewidth $strokewidth"

br=`echo  | gawk "{printf(\"%.0f\",$brm * $dpm / 1000) }"`
echo "Äußerer Bildradius $brm mm wird zu $br Pixel"

rm=`echo  | gawk "{printf(\"%.0f\",$rmm * $dpm / 1000) }"`
file1=`echo $1/* | head -1 `
getsize $file1

#
# Anzahl Bilder
#

num=`ls -1 $1 | wc -l`

#
# Winkel pro bild in Grad
#

deg=`echo  | gawk "{printf(\"%f\",360 / $num) }"`
echo "$num Bilder = ${deg}° pro Bild"


#
# dbauto berechnen
#
rad=`echo "$deg/180*$PI" | bc -l`
dbfitmm=`echo  "$brm/(1/(c($rad/2)) + $in_height/(2*$in_width) / s($rad/2))"  | bc -l`



dbfit=`echo  | gawk "{printf(\"%.0f\",$dbfitmm * $dpm / 1000) }"`


echo "Passender Bildbreite in mm: $dbfitmm = $dbfit Pixel"


if [ $db -eq 0 ]; then
    intrund=`echo $dbfitmm | sed "s/\..*//"`
    if [ $intrund -lt $dbmax ]; then
    db=$dbfitmm
    else
    db=$dbmax
    fi
    echo "Autobildbreite: db=$db mm"
fi




#
# $db / 40mm breites imx
#
imx=`echo  | gawk "{printf(\"%.0f\",$db * $dpm / 1000) }"`
imy=`echo  | gawk "{printf(\"%.0f\",$imx * $in_height/$in_width) }"`

mbmp=`echo  | gawk "{printf(\"%.0f\",$mbm * $dpm / 1000) }"`
mhmp=`echo  | gawk "{printf(\"%.0f\",$mhm * $dpm / 1000) }"`

mradip=`echo  | gawk "{printf(\"%.0f\",$mdia * $dpm / 1000 / 2) }"`


# aussenkreis:
akr=`echo  | gawk "{printf(\"%.0f\",$ad / 2 / 1000 * $dpm) }"`
akx0=$(($xpixel / 2))
aky0=$(($ypixel / 2))
akx1=$akx0
aky1=$(($aky0 + $akr))

# zenralloch
zlr=`echo  | gawk "{printf(\"%.0f\",$zd / 2 / 1000 * $dpm) }"`
zlx0=$(($xpixel / 2))
zly0=$(($ypixel / 2))
zlx1=$zlx0
zly1=$(($zly0 + $zlr))

# zentralkreuz
zkoff=`echo  | gawk "{printf(\"%.0f\",$zd / 2 / sqrt(2) / 1000 * $dpm) }"`
zkx0=$(($xpixel / 2 - $zkoff ))
zky0=$(($ypixel / 2 - $zkoff ))
zkx1=$(($xpixel / 2 + $zkoff ))
zky1=$(($ypixel / 2 + $zkoff ))

#Markierungskreis innen
mkix1=$akx0
mkiy1=$(($aky0 + $rm))

#Markierungskreis aussen
mkax1=$akx0
mkay1=$(($aky0 + $rm + $mbmp))







#
# Convert script erzeugen
# Header

cat<<EOF>>$sc
convert -resize ${xpixel}x${ypixel}! \
-fill none \
-stroke black \
-strokewidth $strokewidth \
-units PixelsPerInch \
-density $dpi \
-draw "
circle $akx0 $aky0 $akx1 $aky1
circle $zlx0 $zly0 $zlx1 $zly1
line   $zkx0 $zky0 $zkx1 $zky1
line   $zkx1 $zky0 $zkx0 $zky1
circle $akx0 $aky0 $mkix1 $mkiy1
circle $akx0 $aky0 $mkax1 $mkay1
EOF
echo -ne "\" -fill black " >> $sc

# "
#
# Convert script erzeugen
# images

#korrwinkel=`echo  | gawk "{printf(\"%f\",atan($imy/(2*$brm)) * 180/ $PI ) }"`
if [ $debug -ge 1 ]; then
    echo Image skalierte x größe imx: $imx
    echo Image skalierte y größe imy: $imy
    echo Aussenradius brm: $brm mm, in Pixel: br: $br
fi
korrwinkel=`echo "a($imy/(2*$br)) * 180 / $PI" | bc -l`
echo "Korrekturwinkel: $korrwinkel"
korrwinkelmark=`echo "a($mhmp/(2*($rm+$mbmp))) * 180 / $PI" | bc -l`
echo "Korrekturwinkel Marker: $korrwinkelmark"

markoffs=-$ARMVERDECKUNGSWINKEL
echo "Marker offset markoffs : $markoffs"
cnt=0
for i in $1/* 
do
  winkel=`echo  | gawk "{printf(\"%f\",360-($cnt * $deg + 0.0001)) }"`
  winkelkorr=`echo  | gawk "{printf(\"%f\",$winkel - 180 - $korrwinkel) }"`
  winkelmark=`echo  | gawk "{printf(\"%f\",$winkel -180 - $markoffs) }"`
  winkelmarkkorr=`echo  | gawk "{printf(\"%f\",$winkelmark  - 180 -  $korrwinkelmark) }"`
#  winkel180=$winkel
if [ $debug -ge 2 ]; then
  echo "Num: $i, Winkel: $winkel Winkelkorr: $winkelkorr winkelmark: $winkelmark winkelmarkkorr: $winkelmarkkorr"
fi
  bildx=` echo  | gawk "{ printf(\"%.0f\", cos($PI*${winkel}/180) * $br + $akx0 ) }"`
  bildy=` echo  | gawk "{ printf(\"%.0f\", sin($PI*${winkel}/180) * $br + $aky0 ) }"`


  OPS="-draw \"translate $bildx,$bildy rotate ${winkelkorr} image over 0,0 $imx,$imy $i\" "
  echo -ne "$OPS" >> $sc

  bildx=` echo  | gawk "{ printf(\"%.0f\", cos($PI*${winkelmark}/180) * $rm + $akx0 ) }"`
  bildy=` echo  | gawk "{ printf(\"%.0f\", sin($PI*${winkelmark}/180) * $rm + $aky0 ) }"`
  bildx2=` echo  | gawk "{ printf(\"%.0f\", cos($PI*${winkelmark}/180) * ($rm-$mradip) + $akx0 ) }"`
  bildy2=` echo  | gawk "{ printf(\"%.0f\", sin($PI*${winkelmark}/180) * ($rm-$mradip) + $aky0 ) }"`

  OPS="-draw \"translate $bildx,$bildy rotate ${winkelmarkkorr} rectangle 0,0 -$mbmp $mhmp \" "
#  OPS="-draw \"circle $bildx $bildy $bildx2 $bildy2 \" "
  echo -ne "$OPS" >> $sc
  cnt=$(($cnt+1))

done

#echo $OPS




#
# Convert script erzeugen
# footer
cat<<EOF>>$sc
 leer.bmp $OUTPDF
EOF


exit 0


Upcoming

Redesign with a peephole like viewer, with the two advantages of having a darker view-area, so less LED-power needed and a lense to better see the small pictures. Where to get these lenses like used in the Plastiskop or ViewMaster?

4 Kommentare:

  1. I am building this to my 2 years old little daughter and when running your script some errors showed up. The convert could not find the "-ne" output in CONVSCRIPT and was missing an "\" at the end of each line.

    I changed the following lines of your script and now the script is working great! Thank you for your job!

    convert -resize ${xpixel}x${ypixel}! \\
    -fill none \\
    -stroke black \\
    -strokewidth $strokewidth \\
    -units PixelsPerInch \\
    -density $dpi \\
    -draw "circle $akx0 $aky0 $akx1 $aky1 circle $zlx0 $zly0 $zlx1 $zly1 line $zkx0 $zky0 $zkx1 $zky1 line $zkx1 $zky0 $zkx0 $zky1 circle $akx0 $aky0 $mkix1 $mkiy1 circle $akx0 $aky0 $mkax1 $mkay1" \\
    EOF
    echo "-fill black \\" >> $sc

    AND

    OPS="-draw \"translate $bildx,$bildy rotate ${winkelkorr} image over 0,0 $imx,$imy $i\" \\"

    AND

    OPS="-draw \"translate $bildx,$bildy rotate ${winkelmarkkorr} rectangle 0,0 -$mbmp $mhmp \" \\"

    AntwortenLöschen
  2. Dear Edras, the "-ne" error and the missing slashes are the source of teh problem. It seems that the built in "echo" command in your shell does not support the "-n" or "-e" option (suppress trailing newline") and therefore also ignores the -e for the slash escapes.

    Thank you for the interest. I am currently working on a better implementation and would encourage you to test my site: http://www.drehkino.de where you can use the program through a web-interface.

    AntwortenLöschen
  3. For the lens - use a fresnel lens. Buy them in sheet sizes.
    Try the effect seen in that great film Brazil in the office (old teleytpes with tiny monitors and fresnel lens screens).
    http://www.youtube.com/watch?feature=player_detailpage&v=enSRvajAIOI#t=49s

    Would also look utterly fantastic on your 3D printed zoetrope.

    AntwortenLöschen
  4. Hello, thanks for your kind sharing. I have built one for interest. But I just use some disc sheets in hands already with a series of only 6 to 12 pictures, and the animation effects are good but a little too fast.
    I would like to know how to slow down the animation effects when the potential meter does not help much.
    And if I do not need the reflection sensor (I want to keep the LEDs flashing whenever I switch on power), how can I modify the circuit? (Sorry, I do not have much background in electronics.)
    By the way, the website http://drehkino.de seems no longer available. Do you have other new webpages?

    AntwortenLöschen