Monday, November 2, 2009

Lego Lip Synching Robot

I just posted my latest creation. I take no credit for the idea, I posted a version earlier in my blog. It is programmed in RobotC and uses simply one sound sensor and one servo motor.

It was a fun build, and I think I will be able to use it in future projects.


  1. What's the code for this like? Is it just a straight relationship between sensor value and rotational distance, or are there some hard-coded thresholds?

    I'm considering bringing a variation of this into the office as a gag.

  2. The sound sensor picks up the intensity of the sound.
    Basically, the mouth opens wider for louder sounds and the mouth closes more for softer sounds. If there is no sound, the mouth tries to go closed (zero). If the sound is louder than it was a moment ago, it opens more and vice versa.

    Here is the RobotC code. It could be improved quite a bit. I thought of some improvements after I posted the video. I hope this helps!

    #pragma config(Sensor, S1, soundsensor, sensorSoundDB)
    #pragma config(Motor, motorA, , tmotorNormal, PIDControl, reversed)
    //*!!Code automatically generated by 'ROBOTC' configuration wizard !!*//

    task main
    int MouthSpeed = 100;
    int MouthPosition = 0;
    int OldMouthPosition = 0;
    int PlayTime = 400;

    nMotorEncoder[motorA] = 0;
    MouthPosition = SensorValue[soundsensor];
    while(time100[T1] < PlayTime) {
    MouthPosition = 2 * SensorValue[soundsensor];
    nxtDisplayBigTextLine(0, "MEA: %d", nMotorEncoder[motorA]);
    nxtDisplayBigTextLine(2, "MP: %d", MouthPosition);

    if (SensorValue[soundsensor] < 15) { //close more
    motor(motorA) = -MouthSpeed;
    while (nMotorEncoder[motorA] > 15){}
    motor(motorA) = 0;
    else if (MouthPosition > OldMouthPosition + 10) { //open wider
    motor(motorA) = MouthSpeed;
    while (nMotorEncoder[motorA] < MouthPosition){}
    motor(motorA) = 0;
    else if (MouthPosition < OldMouthPosition - 10) { //close more
    motor(motorA) = -MouthSpeed;
    while (nMotorEncoder[motorA] > MouthPosition){}
    motor(motorA) = 0;
    else if (MouthPosition == OldMouthPosition) { //stay
    motor(motorA) = 0;
    OldMouthPosition = MouthPosition;


    motor(motorA) = -50;
    while (nMotorEncoder[motorA] > 35){}
    motor(motorA) = 0;