hmkim
Published © GPL3+

Play a Song with Stepper Motor

Play a harmonized song with two stepper motors connected to a PHPoC blue or black and stepper motor smart expansion boards (PES-2403).

BeginnerShowcase (no instructions)8 hours1,081
Play a Song with Stepper Motor

Things used in this project

Hardware components

PHPoC Blue
PHPoC Blue
×1
PHPoC Stepper motor smart expansion board
×2
Stepper motor SE-SM243
×2
DC 12V Power
×2
Jumper wires (generic)
Jumper wires (generic)
×1

Story

Read more

Schematics

Stepper motor smart expansion board(PES-2403)

Stack two stepper motor smart expansion boards on PHPoC Blue.
The ID of the smart expansion board is 13 and 14 which is set with DIP switches.
13: Only 3rd switch is down.
14: Only 4th switch is down.

Stepper motor

Expansion board ----- Stepper motor

M1+ ----- A
M1- ----- A COM
M2+ ----- B
M2- ----- B COM
GND ----- DC12V -
VM ----- DC12V +

Code

Library

PHP
For this project, it needs 2 libraries.
One is sd_spc.php from PSP library, the other is se_step_play.php for playing music.
Library must be included in the lib folder.

- se_step_play.php
<?php
 
include_once "/lib/sd_spc.php";
 
$step_play_speed = 1000; // ms per bar
$step_play_dir = +1;
$step_play_sid = array(0, 0, 0, 0);
 
function step_play_setup($play_id, $sid, $vref = 8, $mode = "half", $accel = 10000)
{
    global $step_play_sid;
 
    if(spc_request_sys($sid, "get did") != "40002403")
        exit("step_play_setup: expansion not found\r\n");
 
    spc_request_dev($sid, "set vref stop 2");
    spc_request_dev($sid, "set vref drive $vref");
    spc_request_dev($sid, "set mode $mode");
    spc_request_dev($sid, "set accel $accel");
 
    $step_play_sid[$play_id] = $sid;
}
 
function step_play_tempo($tempo)
{
    global $step_play_speed;
 
    $step_play_speed = (int)(1000.0 / ($tempo / 60.0));
}
 
function step_play_dir($dir)
{
    global $step_play_dir;
 
    if($dir >= 0)
        $step_play_dir = +1;
    else
        $step_play_dir = -1;
}
 
function step_play_encode($score)
{
    global $step_play_speed;
 
    $score_array = explode(" ", $score);
    $score_count = count($score_array);
 
    $score_encoded = "";
 
    for($i = 0; $i < $score_count; $i++)
    {
        if(!($note = $score_array[$i]))
            continue;
 
        if(strtoupper($note[0]) == "R")
        { /* rest */
            $dur_fp = (float)substr($note, 1);
            $dur_ms = (int)round($step_play_speed / $dur_fp);
 
            $score_encoded .= int2bin(0, 2);
            $score_encoded .= int2bin($dur_ms, 2);
        }
        else
        { /* tone */
            $tone = (int)$note[0] * 12; // octave * 12
 
            // C  C# D  D# E  F  F# G  G# A A# B
            // 0  1  2  3  4  5  6  7  8  9 10 11
 
            switch(strtoupper($note[1]))
            {
                case "C":
                    $tone += 0;
                    break;
                case "D":
                    $tone += 2;
                    break;
                case "E":
                    $tone += 4;
                    break;
                case "F":
                    $tone += 5;
                    break;
                case "G":
                    $tone += 7;
                    break;
                case "A":
                    $tone += 9;
                    break;
                case "B":
                    $tone += 11;
                    break;
                default:
                    exit("encode_score: unknown tone '" . $note[1] . "'\r\n");
                    break;
            }
 
            if($note[2] == "#")
            {
                $tone++;
                $dur_fp = (float)substr($note, 3);
            }
            else
            if($note[2] == "b")
            {
                $tone--;
                $dur_fp = (float)substr($note, 3);
            }
            else
                $dur_fp = (float)substr($note, 2);
 
            $dur_ms = (int)($step_play_speed / $dur_fp);
 
            $octave = $tone / 12;
            $tone = $tone % 12;
 
            $freqA = 440.0 * pow(2, ($octave - 4));
            $freq = (int)round($freqA * pow(2, ($tone - 9) / 12.0));
 
            $score_encoded .= int2bin($freq, 2);
            $score_encoded .= int2bin($dur_ms, 2);
        }
    }
 
    return $score_encoded;
}
 
function step_play_melody($melody)
{
    global $step_play_dir;
    global $step_play_sid;
 
    while($melody)
    {
        $freq = bin2int($melody, 0, 2);
        $dur_ms = bin2int($melody, 2, 2);
 
        if($freq)
        {
            if($step_play_dir > 0)
                spc_request_dev($step_play_sid[0], "goto +1000000 $freq");
            else
                spc_request_dev($step_play_sid[0], "goto -1000000 $freq");
            usleep($dur_ms * 1000);
            spc_request_dev($step_play_sid[0], "stop 0");
        }
        else // zero frequency is 'rest'
            usleep($dur_ms * 1000);
 
        $melody = substr($melody, 4);
    }
}
 
function step_play_harmony($melody1, $melody2)
{
    global $step_play_dir;
    global $step_play_sid;
 
    $pid_st0 = pid_open("/mmap/st0");
    pid_ioctl($pid_st0, "start");
 
    $melody = array($melody1, $melody2);
    $melody_next_ms = array(0, 0);
 
    while($melody[0] || $melody[1] || $melody_next_ms[0] || $melody_next_ms[1])
    {
        for($i = 0; $i < 2; $i++)
        {
            if($melody_next_ms[$i])
            {
                if($melody_next_ms[$i] <= pid_ioctl($pid_st0, "get count"))
                {
                    spc_request_dev($step_play_sid[$i], "stop 0");
                    $melody_next_ms[$i] = 0;
                }
            }
            else
            {
                if($melody[$i])
                {
                    $freq = bin2int($melody[$i], 0, 2);
                    $dur_ms = bin2int($melody[$i], 2, 2);
 
                    $melody[$i] = substr($melody[$i], 4);
 
                    if($freq)
                    {
                        if($step_play_dir > 0)
                            spc_request_dev($step_play_sid[$i], "goto +1000000 $freq");
                        else
                            spc_request_dev($step_play_sid[$i], "goto -1000000 $freq");
                    }
 
                    $melody_next_ms[$i] = pid_ioctl($pid_st0, "get count") + $dur_ms;
                }
            }
        }
    }
 
    pid_close($pid_st0);
}
 
?>

Source code for playing music

PHP
Source code for playing Santa Claus is Coming to Town.

- step_play_santa.php
<?php
 
include_once "/lib/se_step_play.php";
 
function play_santa_claus()
{
    global $step_play_dir;
 
    // Santa Claus is Coming to Town
 
    $melody1a = step_play_encode("4E8 4F8 4G4 4G2.67 4G8 4A8 4B8 5C4 5C2");
    $melody1b = step_play_encode("4E8 4F8 4G8 4G8 4G8 4G8 4G4 4A8 4G8 4F4 4F2");
    $melody1c = step_play_encode("4E4 4G4 4C4 4E4 4D4 4F4 4F4 3B4");
     $melody1d = step_play_encode("4C1 4C1");
 
    $melody2a = step_play_encode("4E8 4F8 4G8 4G8 4G8 4G8 4G4 4A8 4B8 5C8 5C8 5C2");
    $melody2b = step_play_encode("4E8 4F8 4G8 4G8 4G4 4G4 4A8 4G8 4F4 4F2");
    $melody2c = step_play_encode("4E4 4G4 4C4 4E4 4D4 4F4 4F4 3B4");
     $melody2d = step_play_encode("4C1 4C1");
 
    $melody3a = step_play_encode("5D4 5C4 4B4 5C4 4A8 4A8 4A4 4A2");
    $melody3b = step_play_encode("5D4 5C4 4B4 5C4 4A8 4A8 4A8 4A8 4A2");
    $melody3c = step_play_encode("5E4 5D4 5C#4 5D4 4B4 4B4 4B4 4B8 5C8");
    $melody3d = step_play_encode("5D8 5D8 5C8 5C8 4B4 4A4 4G2 4G2");
 
    $melody4a = step_play_encode("4E8 4F8 4G4 4G2.67 4G8 4A8 4B8 5C4 5C2");
    $melody4b = step_play_encode("4E8 4F8 4G8 4G8 4G8 4G8 4G4 4A8 4G8 4F4 4F2");
    $melody4c = step_play_encode("4E4 4G4 4C4 4E4 4D4 4F4 4G4 5D4");
     $melody4d = step_play_encode("5C1 5C1");
 
    $chord1a = step_play_encode("3C4 3E4 3C4 3E4 3F4 3A4 3F4 3A4"); // C    F
    $chord1b = step_play_encode("3C4 3E4 3C4 3E4 3F4 3A4 3F4 3A4"); // C    F
    $chord1c = step_play_encode("3C4 3E4 3C4 3A4 3D4 3F4 3G4 3F4"); // C Am Dm G7
    $chord1d = step_play_encode("3C4 3E4 3C4 3E4 3F4 3A4 3G4 3F4"); // C    F G7
 
    $chord2a = step_play_encode("3C4 3E4 3C4 3E4 3F4 3A4 3F4 3A4"); // C    F
    $chord2b = step_play_encode("3C4 3E4 3C4 3E4 3F4 3A4 3F4 3A4"); // C    F
    $chord2c = step_play_encode("3C4 3E4 3C4 3A4 3D4 3F4 3G4 3F4"); // C Am Dm G7
    $chord2d = step_play_encode("3C4 3E4 3C4 3E4 3C1");             // C    C
 
    $chord3a  = step_play_encode("3D8 3B8 3G8 3B8 3D8 3B8 3G8 3B8"); // G
    $chord3a .= step_play_encode("3C8 3A8 3F8 3A8 3C8 3A8 3F8 3A8"); // F
    $chord3b  = step_play_encode("3D8 3A8 3F8 3A8 3D8 3A8 3F8 3A8"); // Dm
    $chord3b .= step_play_encode("3C8 3A8 3F8 3A8 3C8 3A8 3F8 3A8"); // F
    $chord3c  = step_play_encode("3C#8 3A8 3C#8 3E8 3C#8 3A8 3C#8 3E8"); // A
    $chord3c .= step_play_encode("3D8 3B8 3G8 3B8 3D8 3B8 3G8 3B8"); // G
    $chord3d  = step_play_encode("3C8 3A8 3F#8 3A8 3C8 3A8 3F#8 3A8"); // D7
    $chord3d .= step_play_encode("3D8 3B8 3F8 3B8 3D8 3B8 3F8 3B8"); // G7
 
    $chord4a = step_play_encode("3C4 3E4 3C4 3E4 3F4 3A4 3F4 3A4"); // C    F
    $chord4b = step_play_encode("3C4 3E4 3C4 3E4 3F4 3A4 3F4 3A4"); // C    F
    $chord4c = step_play_encode("3C4 3E4 3C4 3A4 3D4 3F4 3G4 3F4"); // C Am Dm G7
    $chord4d = step_play_encode("3C4 3E4 3F4 3A4 3C1");             // C F  C
 
    step_play_dir(+1);
    step_play_harmony($melody1a, $chord1a);
    step_play_dir(-1);
    step_play_harmony($melody1b, $chord1b);
    step_play_dir(+1);
    step_play_harmony($melody1c, $chord1c);
    step_play_dir(-1);
    step_play_harmony($melody1d, $chord1d);
 
    step_play_dir(+1);
    step_play_harmony($melody2a, $chord2a);
    step_play_dir(-1);
    step_play_harmony($melody2b, $chord2b);
    step_play_dir(+1);
    step_play_harmony($melody2c, $chord2c);
    step_play_dir(-1);
    step_play_harmony($melody2d, $chord2d);
 
    step_play_dir(+1);
    step_play_harmony($melody3a, $chord3a);
    step_play_dir(-1);
    step_play_harmony($melody3b, $chord3b);
    step_play_dir(+1);
    step_play_harmony($melody3c, $chord3c);
    step_play_dir(-1);
    step_play_harmony($melody3d, $chord3d);
 
    step_play_dir(+1);
    step_play_harmony($melody4a, $chord4a);
    step_play_dir(-1);
    step_play_harmony($melody4b, $chord4b);
    step_play_dir(+1);
    step_play_harmony($melody4c, $chord4c);
    step_play_dir(-1);
    step_play_harmony($melody4d, $chord4d);
}
 
spc_reset();
spc_sync_baud(460800);
 
step_play_setup(0, 13);
step_play_setup(1, 14);
step_play_tempo(30);
 
play_santa_claus();
 
?>

Credits

hmkim

hmkim

1 project • 24 followers

Comments