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
####
#
# 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?