Lost in Space banner

ELECTRONIC EXPERIMENTS

Continuous Rotation Servo Motor

Blinking Chest Lights Rev 1.0

Blinking Chest Lights Rev 3.0

Sound Display VU Meter Using A Microphone

Printed Circuit Board for Chest Lights

Return to Skips Messy Workbench Homepage

CONTINUOUS ROTATION SERVO MOTOR

As it's name describes, a continuous rotation servo is a servo motor that rotates 360°. Regular servo motors can only rotate 180°. Other than rotation angle, following are some of the differences:

Beware that the two types of servo motors look exactly the same except for the label. Be sure to read the label on the servo motor. The following photo shows a continuous rotation servo motor on the left and a standard servo motor on the right. These motors are also wired the same, see the schematic of the circuit I used while learning about the continuous rotation servo motor.

Continuous and standard servo look the same

How a continuous rotation motor works

This explanation will be assuming the motor will be wired to an Arduino micro processor board. It can be any of the various Arduino boards provided they have at least one output pin that is a Pulse Width Modulation (PWM) pin. On an Arduino Uno these pins are marked with a Tilde (~). For other board check the data sheet for that board.

The motor speed and direction are controlled by sending a PWM pulse to the motor between 0.50mS to 2.50mS. The pulse width is controlled by writing a value of 0 to 180 to the PWM pin.

Pulses describing continuous servo operation

Figures 1 through 3 show the pulse width that is sent to a continuous rotation servo motor to make it run. A short video is included of the motor and an oscilloscope screen showing the pulse change versus motor action.

Figure 1 shows a pulse width of 0.50mS. The width from 1.5mS to 0.50mS is 1.0mS and is created by values in the range of 0 to 89 being written to the PWM pin that the motor is attached to. When the pulse varies from 1.50mS to 0.50mS (value of 90 to 0), the motor will be turning clock-wise (CW). At a value of 89 the motor will be turning CW and running very slow. As the value being written is decrease toward zero (0), the motor will continue turning CW and will increase in speed until achieving full speed in the CW direction at a value of zero (0).

Figure 2 shows a pulse width of 1.50mS. When the pulse width is 1.50mS the value written to the PWM pin that the motor is attached to is 90 and the motor is stopped.

Figure 3 shows a pulse width of 2.50mS. The width from 1.50mS to 2.50mS is 1.0mS and is created by values in the range of 91 to 180 being written to the PWM pin that the motor is attached to. When the pulse varies from 1.50mS to 2.50mS (value of 91 to 180), the motor will be turning counter-clock-wise (CCW). At the value of 91 the motor will be turning CCW and running very slow. As the value being written is increased toward 180, the motor will continue turning CCW and will increase in speed until achieving full speed in the CCW direction at a value of 180.



Continuous rotation servo adjustment location

Click to enlarge image





Schematic Diagram and Bill of Material (BOM)

Schematic Diagram

Here is the schematic diagram that is using an Arduino UNO. Most any Arduino board can be used as long as there is at least one PWM output pin available. The schematic was created using Easy EDA. Click the schematic image to enlarge.

Schematic of continuous rotation servo with Arduino UNO

Bill of Material (BOM)

Prices are as of March 11, 2024

Quantity Description Part Number Vendor ASIN Number Price Per Extended Price
1 Arduino Uno or similar Uno R3 [A000066] Amazon B008GRTSV6 $27.60 $27.60
1 Continuous rotation servo FS90R Adafruit.com N/A $7.50 $7.50
3 Male-to-Male wire jumpers
Set of 130pcs 12, 16, 20, 25cm
Only 3 wires required for this project
41383 Amazon B016KI622U $0.06 per wire $0.18

Program Code Used to Test Motor with Explanation

The code in the following window can be selected, copied and pasted directly into your IDE. It should work well on a Windows or Mac. Simply place you mouse cursor where you want to start copying and then click and drag to select the text. Then copy the selection and paste it into your Integrated Development Environment (IDE).

Program code I wrote to learn how to use the continuous rotation Servo

                    
// Testing Continuous Servo Test Code
// John G. (Skip) Todora
// Date: February 29, 2024

/*
  Servo.h Methods:
    attach()
    write()
    writeMicroseconds()
    read()
    attached()
    detach()
*/

/* 
    Motor Number: FS90R - From Adafruit.com

    To control with an Arduino, Adafruit suggest connecting the orange control wire 
    to pin 9 or 10 and using the Servo library included with the Arduino 
    IDE. 
    Write a value of "90" (1.5ms pulse) to the PWM pin to stop the motor. 
    Write a value of 180, (2.50ms pulse) is full speed CCW.
    Write a value of zero '0' (0.50ms pulse) is full speed CW.
    The motor may require some simple calibration. Simply tell the servo 
    to 'stop' and then gently adjust the potentiometer in the recessed hole 
    on the bottom of the servo using a small screwdriver until the servo stops moving.

    *** 
        During testing this is what I discovered:
        CW direction count down from 89 to 0, pulse width = 0.50mS (1.0mS less than full stop)
        CCW direction count up from 91 to 180, pulse width = 2.5mS (1.0mS greater than full stop)
        Motor stopped count = 90, pulse width = 1.5mS
        Adjustment screw on bottom of motor to tweak the motor stop position
    ***

    MOTOR SPECIFICATIONS
    No load speed: 110RPM (4.8v) / 130RPM (6v)
    Running Current (at no load): 100mA (4.8v) / 120mA (6v)
    Peak Stall Torque (4.8v): 1.3 kg/cm / 18.09 oz/in
    Peak Stall Torque (6v): 1.5 kg/cm / 20.86 oz/in
    Stall Current: 550mA (4.8v) / 650mA (6v)
    Dimensions: 32mm x 30mm x 12mm / 1.3" x 1.2" x 0.5"
    Wire Length: 240mm / 9.4"
    Weight: 10g
    Spline Count: 21
*/

#include<servo.h> // Include the servo library.

#define servoMtr 10   // Assign the servo motor to pin 10

Servo myServo;  // Create a servo object

int i = 90;			  // Motor stopped
int rotDir = 0;		// 0 = CCW, 1 = CW. Not really for rotation. Flag used to change operation

void setup() {
  Serial.begin(9600);         // Set up the Serial port
  myServo.attach(servoMtr);   // Attach the servo object to the defined pin
  myServo.write(90);          // Make sure the motor is stopped
}

void loop() {
  
  // Count up from 90 to 180. CCW stop to full speed
  if (rotDir == 0) {
    Serial.print("i = "); Serial.print(i); Serial.print("   ");   // Can be removed
    Serial.print("rotDir = "); Serial.println(rotDir);            // Can be removed
    i++;
    myServo.write(i);
    delay(300);                                                   // Can be removed
    if (i == 180) {
      rotDir = 1;
      Serial.print("i = "); Serial.print(i); Serial.print("   "); // Can be removed
      Serial.print("rotDir = "); Serial.println(rotDir);          // Can be removed
    }
  }
  
  // Count down from 180 to 90. CCW full speed to stop
  if (rotDir == 1) {
    Serial.print("i = "); Serial.print(i); Serial.print("   ");   // Can be removed
    Serial.print("rotDir = "); Serial.println(rotDir);            // Can be removed
    i--;
    myServo.write(i);
    delay(300);                                                   // Can be removed
    if (i == 90) {
      rotDir = 2;
      Serial.print("i = "); Serial.print(i); Serial.print("   "); // Can be removed
      Serial.print("rotDir = "); Serial.println(rotDir);          // Can be removed
    }
  }
  
  // Count down from 90 to 0. Stop to CW full speed
  if (rotDir == 2) {
    Serial.print("i = "); Serial.print(i); Serial.print("   ");   // Can be removed
    Serial.print("rotDir = "); Serial.println(rotDir);            // Can be removed
    i--;
    myServo.write(i);
    delay(300);                                                   // Can be removed
    if (i == 0) {
      rotDir = 3;
      Serial.print("i = "); Serial.print(i); Serial.print("   "); // Can be removed
      Serial.print("rotDir = "); Serial.println(rotDir);          // Can be removed
    }
  }
  
  // Count up from 0 to 90. Full speed CW to stop
  if (rotDir == 3) {
    Serial.print("i = "); Serial.print(i); Serial.print("   ");   // Can be removed
    Serial.print("rotDir = "); Serial.println(rotDir);            // Can be removed
    i++;
    myServo.write(i);
    delay(300);                                                   // Can be removed
    if (i == 90) {
      rotDir = 0;
      Serial.print("i = "); Serial.print(i); Serial.print("   "); // Can be removed
      Serial.print("rotDir = "); Serial.println(rotDir);          // Can be removed 
    }
  }
}

                


Explanation of the code

This video is best viewed in full screen mode.

RETURN TO TOP OF PAGE


BLINKING CHEST LIGHTS Rev 1.0, PROGRAM Rev 2.0

As it's name describes, this section will demonstrate my first attempt at blinking the robots chest lights, the Function Indicators, in a completely random pattern.

This experiment uses an Arduino Mega 2560 board. This board will not be used in the final robot animation because the Mega board is too large to be self contained within the robot body.

Random Blinking of Function Lights Testing

Schematic Diagram and Bill of Material (BOM)

Schematic Diagram Rev 1.0

Here is the schematic diagram that is using an Arduino Mega 2560. Most any Arduino board can be used. The schematic was created using Easy EDA. Click the schematic image to enlarge.

Schematic of robot chest lights using Arduino Mega 2560

Bill of Material (BOM)

Prices are as of March 11, 2024

Quantity Description Part Number Vendor ASIN Number Price Per Extended Price
1 Arduino Mega 2560 or similar Mega 2560 Rev3 [A000067] Amazon B0046AMGW0 $48.90 $48.90
22 LED, 5mm Defused
Pack - 5 LEDs each
in 5 colors
25-pack
4203 Adafruit.com N/A $4.95 $4.95
22 YOKIVE 100 pcs Carbon Film
Resistors, 1/4W, 300Ω 5%
Amazon B0BNHTXS1S $0.0499 $1.098
24 Male-to-Male wire jumpers
Set of 130pcs 12, 16, 20, 25cm
Only 3 wires required for this project
41383 Amazon B016KI622U $0.06 per wire $0.18

Program Code Used to Test Random Blinking of Function Indicators Rev 2.0

The code in the following window can be selected, copied and pasted directly into your IDE. It should work well on a Windows or Mac. Simply place you mouse cursor where you want to start copying and then click and drag to select the text. Then copy the selection and paste it into your Integrated Development Environment (IDE).

Program code I wrote to produce random blinking of LED's

// Blink without using delay and using a random 
// number for the duty cycle

// Programmed for an Arduino Mega or Arduino Mega 2560
// By: John G. (Skip) Todora
// Date: March 03, 2024
// Revision: 02

// B9 Robot chest lights: Function Indicators and Programming Buttons

// Two rows of six lights per row; small round lamps
// Bottom row of Function Indicators
#define botRow00 22
#define botRow01 24
#define botRow02 26
#define botRow03 28
#define botRow04 30
#define botRow05 32

// Top row of Function Indicators
#define topRow00 23
#define topRow01 25
#define topRow02 27
#define topRow03 29
#define topRow04 31
#define topRow05 33

// Bottom rows of five lights per row; Programming Buttons
#define botRowSq00 44
#define botRowSq01 46
#define botRowSq02 48
#define botRowSq03 50
#define botRowSq04 52

// Top rows or five lights per row: Programming Buttons
#define topRowSq00 45
#define topRowSq01 47
#define topRowSq02 49
#define topRowSq03 51
#define topRowSq04 53

// The variable: range and min form the data for creating a duty cycle for blinking
// These values will most likely need to be adjusted depending upon what processor
// board is being used.
unsigned long range = 80000;  // Max duty cycle for blink in mS
unsigned long min = 700;      // Min duty cycle for blink in mS

int runOnce = 1;              // Used for lamp test on power up

// Variable to store the current time
// unsigned long curTime = 0;

// Bottom row of the six; Function Indicators
// Assign Current Time and Previous time values
unsigned long botRow00CurTime = 0;
unsigned long botRow01CurTime = 0;
unsigned long botRow02CurTime = 0;
unsigned long botRow03CurTime = 0;
unsigned long botRow04CurTime = 0;
unsigned long botRow05CurTime = 0;
unsigned long botRow00PrevTime = 0;
unsigned long botRow01PrevTime = 0;
unsigned long botRow02PrevTime = 0;
unsigned long botRow03PrevTime = 0;
unsigned long botRow04PrevTime = 0;
unsigned long botRow05PrevTime = 0;

// Top row of the six; Function Indicators
// Assign Current Time and Previous time values
unsigned long topRow00CurTime = 0;
unsigned long topRow01CurTime = 0;
unsigned long topRow02CurTime = 0;
unsigned long topRow03CurTime = 0;
unsigned long topRow04CurTime = 0;
unsigned long topRow05CurTime = 0;
unsigned long topRow00PrevTime = 0;
unsigned long topRow01PrevTime = 0;
unsigned long topRow02PrevTime = 0;
unsigned long topRow03PrevTime = 0;
unsigned long topRow04PrevTime = 0;
unsigned long topRow05PrevTime = 0;

// Bottom row of five square: Programming Buttons
// Assign Current Time values. Previous time not needed because 
// these lights do not blink
unsigned long botRowSq00CurTime = 0;
unsigned long botRowSq01CurTime = 0;
unsigned long botRowSq02CurTime = 0;
unsigned long botRowSq03CurTime = 0;
unsigned long botRowSq04CurTime = 0;

// Top row of five square: Programming Buttons
// Assign Current Time values. Previous time not needed because 
// these lights do not blink
unsigned long topRowSq00CurTime = 0;
unsigned long topRowSq01CurTime = 0;
unsigned long topRowSq02CurTime = 0;
unsigned long topRowSq03CurTime = 0;
unsigned long topRowSq04CurTime = 0;

// Initialize state of bottom row of small round lights: 
// Function Indicators
int botRow00State = LOW;
int botRow01State = LOW;
int botRow02State = LOW;
int botRow03State = LOW;
int botRow04State = LOW;
int botRow05State = LOW;

// Intitialize state of top row of small round lights:
// Function Indicators
int topRow00State = LOW;
int topRow01State = LOW;
int topRow02State = LOW;
int topRow03State = LOW;
int topRow04State = LOW;
int topRow05State = LOW;

// Initialize state of bottom row of square lights:
// Programming Push Buttons
int botRowSq00State = LOW;
int botRowSq01State = LOW;
int botRowSq02State = LOW;
int botRowSq03State = LOW;
int botRowSq04State = LOW;

// Initialize state of top row of square lights
// Programming Push Buttons
int topRowSq00State = LOW;
int topRowSq01State = LOW;
int topRowSq02State = LOW;
int topRowSq03State = LOW;
int topRowsq04State = LOW;

void setup() {
  Serial.begin(9600);
  
  // Declare all lamp pins as data outputs
  pinMode(botRow00, OUTPUT);
  pinMode(botRow01, OUTPUT);
  pinMode(botRow02, OUTPUT);
  pinMode(botRow03, OUTPUT);
  pinMode(botRow04, OUTPUT);
  pinMode(botRow05, OUTPUT);
  
  pinMode(topRow00, OUTPUT);
  pinMode(topRow01, OUTPUT);
  pinMode(topRow02, OUTPUT);
  pinMode(topRow03, OUTPUT);
  pinMode(topRow04, OUTPUT);
  pinMode(topRow05, OUTPUT);

  pinMode(botRowSq00, OUTPUT);
  pinMode(botRowSq01, OUTPUT);
  pinMode(botRowSq02, OUTPUT);
  pinMode(botRowSq03, OUTPUT);
  pinMode(botRowSq04, OUTPUT);

  pinMode(topRowSq00, OUTPUT);
  pinMode(topRowSq01, OUTPUT);
  pinMode(topRowSq02, OUTPUT);
  pinMode(topRowSq03, OUTPUT);
  pinMode(topRowSq04, OUTPUT);
}

void loop() {
  // Run once - Lamp Test
  if (runOnce == 1) {
    lampTest();   // Function that controls lamp test
  }
    
  // Assign millis() to each light
  // curTime = millis();
  
  botRow00CurTime = millis();
  botRow01CurTime = millis();
  botRow02CurTime = millis();
  botRow03CurTime = millis();
  botRow04CurTime = millis();
  botRow05CurTime = millis();
  
  topRow00CurTime = millis();
  topRow01CurTime = millis();
  topRow02CurTime = millis();
  topRow03CurTime = millis();
  topRow04CurTime = millis();
  topRow05CurTime = millis();
  
  
  // Control the lights
  // Bottom Row LED 00
  unsigned long botRow00DutyCycle = rand() % range + min; // rand() C stdlib.h (0 to 32767)
  if (botRow00CurTime - botRow00PrevTime > botRow00DutyCycle / 2) {
  // if (curTime - botRow00PrevTime > botRow00DutyCycle / 2) {
    botRow00Blink();
    botRow00PrevTime = botRow00CurTime;
  }
    
  // Bottom Row LED 01
  unsigned long botRow01DutyCycle = rand() % range + min;
  if (botRow01CurTime - botRow01PrevTime > botRow01DutyCycle / 2) {
  // if (curTime - botRow01PrevTime > botRow01DutyCycle / 2) {
    botRow01Blink();
    botRow01PrevTime = botRow01CurTime;
  }
   
  // Bottom Row LED 02
  unsigned long botRow02DutyCycle = rand() % range + min;
  if (botRow02CurTime - botRow02PrevTime > botRow02DutyCycle / 2) {
  // if (curTime - botRow02PrevTime > botRow02DutyCycle / 2) {
    botRow02Blink();
    botRow02PrevTime = botRow02CurTime;
  }
    
  // Bottom Row LED 03
  unsigned long botRow03DutyCycle = rand() % range + min;
  if (botRow03CurTime - botRow03PrevTime > botRow03DutyCycle / 2) {
  // if (curTime - botRow03PrevTime > botRow03DutyCycle / 2) {  
    botRow03Blink();
    botRow03PrevTime = botRow03CurTime;
  }
    
  // Bottom Row LED 04
  unsigned long botRow04DutyCycle = rand() % range + min;
  if (botRow04CurTime - botRow04PrevTime > botRow04DutyCycle / 2) {
  // if (curTime - botRow04PrevTime > botRow04DutyCycle / 2) {
    botRow04Blink();
    botRow04PrevTime = botRow04CurTime;
  }
    
  // Bottom Row LED 05
  unsigned long botRow05DutyCycle = rand() % range + min;
  if (botRow05CurTime - botRow05PrevTime > botRow05DutyCycle / 2) {
  // if (curTime - botRow05PrevTime > botRow05DutyCycle / 2) {
    botRow05Blink();
    botRow05PrevTime = botRow05CurTime;
  }
    
  
  
  // Top Row LED 00
  unsigned long topRow00DutyCycle = rand() % range + min;
  if (topRow00CurTime - topRow00PrevTime > topRow00DutyCycle / 2) {
  // if (curTime - topRow00PrevTime > topRow00DutyCycle / 2) {
    topRow00Blink();
    topRow00PrevTime = topRow00CurTime;
  }
    
  // Top Row LED 01
  unsigned long topRow01DutyCycle = rand() % range + min;
  if (topRow01CurTime - topRow01PrevTime > topRow01DutyCycle / 2) {
  // if (curTime - topRow01PrevTime > topRow01DutyCycle / 2) {
    topRow01Blink();
    topRow01PrevTime = topRow01CurTime;
  }
    
  // Top Row LED 02
  unsigned long topRow02DutyCycle = rand() % range + min;
  if (topRow02CurTime - topRow02PrevTime > topRow02DutyCycle / 2) {
  // if (curTime - topRow02PrevTime > topRow02DutyCycle / 2) {  
    topRow02Blink();
    topRow02PrevTime = botRow02CurTime;
  }
    
  // Top Row LED 03
  unsigned long topRow03DutyCycle = rand() % range + min;
  if (topRow03CurTime - topRow03PrevTime > topRow03DutyCycle / 2) {
  // if (curTime - topRow03PrevTime > topRow03DutyCycle / 2) {  
    topRow03Blink();
    topRow03PrevTime = topRow03CurTime;
  }
    
  // Top Row LED 04
  unsigned long topRow04DutyCycle = rand() % range + min;
  if (topRow04CurTime - topRow04PrevTime > topRow04DutyCycle / 2) {
  // if (curTime - topRow04PrevTime > topRow04DutyCycle / 2) {  
    topRow04Blink();
    topRow04PrevTime = topRow04CurTime;
  }
    
  // Top Row LED 05
  unsigned long topRow05DutyCycle = rand() % range + min;
  if (topRow05CurTime - topRow05PrevTime > topRow05DutyCycle / 2) {
  // if (curTime - topRow05PrevTime > topRow05DutyCycle / 2) {
    topRow05Blink();
    topRow05PrevTime = topRow05CurTime;
  }
}

void lampTest() {
  digitalWrite(botRow00, HIGH);
    delay(500);
    digitalWrite(botRow01, HIGH);
    delay(500);
    digitalWrite(botRow02, HIGH);
    delay(500);
    digitalWrite(botRow03, HIGH);
    delay(500);
    digitalWrite(botRow04, HIGH);
    delay(500);
    digitalWrite(botRow05, HIGH);
    delay(500);
    digitalWrite(topRow00, HIGH);
    delay(500);
    digitalWrite(topRow01, HIGH);
    delay(500);
    digitalWrite(topRow02, HIGH);
    delay(500);
    digitalWrite(topRow03, HIGH);
    delay(500);
    digitalWrite(topRow04, HIGH);
    delay(500);
    digitalWrite(topRow05, HIGH);
    delay(500);
    digitalWrite(botRowSq00, HIGH);
    delay(500);
    digitalWrite(botRowSq01, HIGH);
    delay(500);
    digitalWrite(botRowSq02, HIGH);
    delay(500);
    digitalWrite(botRowSq03, HIGH);
    delay(500);
    digitalWrite(botRowSq04, HIGH);
    delay(500);
    digitalWrite(topRowSq00, HIGH);
    delay(500);
    digitalWrite(topRowSq01, HIGH);
    delay(500);
    digitalWrite(topRowSq02, HIGH);
    delay(500);
    digitalWrite(topRowSq03, HIGH);
    delay(500);
    digitalWrite(topRowSq04, HIGH);
    delay(2000);    // Adjust to user liking
    runOnce = 0;
    digitalWrite(botRow00, LOW);
    digitalWrite(botRow01, LOW);
    digitalWrite(botRow02, LOW);
    digitalWrite(botRow03, LOW);
    digitalWrite(botRow04, LOW);
    digitalWrite(botRow05, LOW);
    digitalWrite(topRow00, LOW);
    digitalWrite(topRow00, LOW);
    digitalWrite(topRow00, LOW);
    digitalWrite(topRow00, LOW);
    digitalWrite(topRow00, LOW);
    digitalWrite(topRow00, LOW);

    /*
    digitalWrite(botRowSq00, LOW);
    digitalWrite(botRowSq01, LOW);
    digitalWrite(botRowSq02, LOW);
    digitalWrite(botRowSq03, LOW);
    digitalWrite(botRowSq04, LOW);
    digitalWrite(topRowSq00, LOW);
    digitalWrite(topRowSq01, LOW);
    digitalWrite(topRowSq02, LOW);
    digitalWrite(topRowSq03, LOW);
    digitalWrite(topRowSq04, LOW);
    */
}

// Bottom row Function Indicators Blink
void botRow00Blink() {
  botRow00State = (botRow00State == HIGH) ? LOW : HIGH;
  digitalWrite(botRow00, botRow00State);
}

void botRow01Blink() {
  botRow01State = (botRow01State == HIGH) ? LOW : HIGH;
  digitalWrite(botRow01, botRow01State);
}

void botRow02Blink() {
  botRow02State = (botRow02State == HIGH) ? LOW : HIGH;
  digitalWrite(botRow02, botRow02State);
}

void botRow03Blink() {
  botRow03State = (botRow03State == HIGH) ? LOW : HIGH;
  digitalWrite(botRow03, botRow03State);
}

void botRow04Blink() {
  botRow04State = (botRow04State == HIGH) ? LOW : HIGH;
  digitalWrite(botRow04, botRow04State);
}

void botRow05Blink() {
  botRow05State = (botRow05State == HIGH) ? LOW : HIGH;
  digitalWrite(botRow05, botRow05State);
}

// Top row Function Indicators Blink

void topRow00Blink() {
  topRow00State = (topRow00State == HIGH) ? LOW : HIGH;
  digitalWrite(topRow00, topRow00State);
}

void topRow01Blink() {
  topRow01State = (topRow01State == HIGH) ? LOW : HIGH;
  digitalWrite(topRow01, topRow01State);
}

void topRow02Blink() {
  topRow02State = (topRow02State == HIGH) ? LOW : HIGH;
  digitalWrite(topRow02, topRow02State);
}

void topRow03Blink() {
  topRow03State = (topRow03State == HIGH) ? LOW : HIGH;
  digitalWrite(topRow03, topRow03State);
}

void topRow04Blink() {
  topRow04State = (topRow04State == HIGH) ? LOW : HIGH;
  digitalWrite(topRow04, topRow04State);
}

void topRow05Blink() {
  topRow05State = (topRow05State == HIGH) ? LOW : HIGH;
  digitalWrite(topRow05, topRow05State);
}
                


Explanation of the code

This video is best viewed in full screen mode.

RETURN TO TOP OF PAGE


BLINKING CHEST LIGHTS Rev 1.1, PROGRAM Rev 3.0

As it's name describes, this section will demonstrate my second, actually third attempt at blinking the robots chest lights; the Function Indicators, in a completely random pattern, and the Sensor Indicators either back-and-forth at a random rate or at a fixed equal time interval. In this experiment I'm using an Arduino Micro and I paralleled three of the Function Indicator LED's, in a random arrangement, off of a single Arduino output pin (See the schematic diagram). I did this to save output pins but to also check if the lights still look as if they are blinking in a random pattern. Following is a short video of this design:

This video is best viewed in full screen mode.

Schematic Diagram and Bill of Material (BOM)

Schematic Diagram Rev 3.0

Here is the schematic diagram that is using an Arduino Mega 2560. Most any Arduino board can be used. The schematic was created using Easy EDA. Click the schematic image to enlarge.

Schematic of robot chest lights using Arduino Uno and less output pins

Bill of Material (BOM)

Prices are as of March 11, 2024

Quantity Description Part Number Vendor ASIN Number Price Per Extended Price
1 Arduino Mega 2560 or similar Mega 2560 Rev3 [A000067] Amazon B0046AMGW0 $48.90 $48.90
24 LED, 5mm Defused
Pack - 5 LEDs each
in 5 colors
25-pack
4203 Adafruit.com N/A $4.95 $4.95
24 YOKIVE 100 pcs Carbon Film
Resistors, 1/4W, 300Ω 5%
Amazon B0BNHTXS1S $0.0499 $1.098
24 Male-to-Male wire jumpers
Set of 130pcs 12, 16, 20, 25cm
Only 3 wires required for this project
41383 Amazon B016KI622U $0.06 per wire $0.18

Program Code Used to Test Blinking Chest Lights Using Groups Rev. 3.0

The code in the following window can be selected, copied and pasted directly into your IDE. It should work well on a Windows or Mac. Simply place you mouse cursor where you want to start copying and then click and drag to select the text. Then copy the selection and paste it into your Integrated Development Environment (IDE).

Program code I wrote to produce random blinking of LED's

// Blink without using delay and using a random 
// number for the duty cycle

// Programmed for an Arduino Mega or Arduino Mega 2560
// By: John G. (Skip) Todora
// Date: March 16, 2024
// Revision: 3.0
// Filename: Light_Test_with_Micro_using_4-Outputs.ino

// B9 Robot chest lights: Function Indicators and Sensor Indicators

// Two rows of six lights per row; Function Indicators
// The 12-lights are 4-groups of 3-lights/group
// Pin assignment for Function Indicators and for Sensor Indicators
#define group01 2       // D1, D5, D9 - See schematic diagram
#define group02 3       // D2, D8, D10 - See schematic diagram
#define group03 4       // D3, D6, D11 - See schematic diagram
#define group04 5       // D4, D7, D12 - See schematic diagram
#define sensorInd01 6   // Sensor indicator
#define sensorInd02 7   // Sensor indicator

// The variable: range and min form the data for creating a duty cycle for blinking
// These values will most likely need to be adjusted depending upon what processor
// board is being used.
unsigned long range = 80000;  // Max duty cycle for blink in mS
unsigned long min = 700;      // Min duty cycle for blink in mS

int runOnce = 1;              // Used for lamp test on power up

// Assign Current Time and Previous time values
unsigned long group01CurTime = 0;
unsigned long group02CurTime = 0;
unsigned long group03CurTime = 0;
unsigned long group04CurTime = 0;
unsigned long sensorInd01CurTime = 0;
unsigned long sensorInd02CurTime = 0;
unsigned long group01PrevTime = 0;
unsigned long group02PrevTime = 0;
unsigned long group03PrevTime = 0;
unsigned long group04PrevTime = 0;
unsigned long sensorInd01PrevTime = 0;
unsigned long sensorInd02PrevTime = 0;

// Initialize state of bottom row of small round lights: 
// Function Indicators
int group01State = LOW;
int group02State = LOW;
int group03State = LOW;
int group04State = LOW;
int sensorInd01State = LOW;
int sensorInd02State = LOW;

void setup() {
  Serial.begin(9600);
  
  // Declare all lamp pins as data outputs
  pinMode(group01, OUTPUT);
  pinMode(group02, OUTPUT);
  pinMode(group03, OUTPUT);
  pinMode(group04, OUTPUT);
  pinMode(sensorInd01, OUTPUT);
  pinMode(sensorInd02, OUTPUT);
}

void loop() {
  // Run once - Lamp Test
  if (runOnce == 1) {
    lampTest();   // Function that controls lamp test
  }
    
  // Assign millis() to each light
  // curTime = millis();
  group01CurTime = millis();
  group02CurTime = millis();
  group03CurTime = millis();
  group04CurTime = millis();
  sensorInd01CurTime = millis();
  sensorInd02CurTime = millis();
  
  // Control the lights
  // Group 01 - D1, D5, D9
  unsigned long group01DutyCycle = rand() % range + min; // rand() C stdlib.h (0 to 32767)
  if (group01CurTime - group01PrevTime > group01DutyCycle / 2) {
     group01Blink();
    group01PrevTime = group01CurTime;
  }
    
  // Group 02 - D3, D8, D10
  unsigned long group02DutyCycle = rand() % range + min;
  if (group02CurTime - group02PrevTime > group02DutyCycle / 2) {
    group02Blink();
    group02PrevTime = group02CurTime;
  }
   
  // Group 03 - D3, D6, D11
  unsigned long group03DutyCycle = rand() % range + min;
  if (group03CurTime - group03PrevTime > group03DutyCycle / 2) {
    group03Blink();
    group03PrevTime = group03CurTime;
  }
    
  // Group 04 - D4, D7, D12
  unsigned long group04DutyCycle = rand() % range + min;
  if (group04CurTime - group04PrevTime > group04DutyCycle / 2) {
    group04Blink();
    group04PrevTime = group04CurTime;
  }
    
  // Sensor Indicator 01
  unsigned long sensorInd01DutyCycle = rand() % range + min;
  if (sensorInd01CurTime - sensorInd01PrevTime > sensorInd01DutyCycle / 2) {
     sensorInd01Blink();
    sensorInd01PrevTime = sensorInd01CurTime;
  }
    
  // Sensor Indicator 02
  unsigned long sensorInd02DutyCycle = rand() % range + min;
  if (sensorInd02CurTime - sensorInd02PrevTime > sensorInd02DutyCycle / 2) {
     sensorInd02Blink();
    sensorInd02PrevTime = sensorInd02CurTime;
  }
}

void lampTest() {
  digitalWrite(group01, HIGH);
  delay(500);
  digitalWrite(group02, HIGH);
  delay(500);
  digitalWrite(group03, HIGH);
  delay(500);
  digitalWrite(group04, HIGH);
  delay(500);
  digitalWrite(sensorInd01, HIGH);
  delay(500);
  digitalWrite(sensorInd02, HIGH);
  delay(2000);
  runOnce = 0;
  digitalWrite(group01, LOW);
  digitalWrite(group02, LOW);
  digitalWrite(group03, LOW);
  digitalWrite(group04, LOW);
  digitalWrite(sensorInd01, LOW);
  digitalWrite(sensorInd02, LOW);
  delay(500);
}


// Change the state of Group 01 Function Indicators
void group01Blink() {
  group01State = (group01State == HIGH) ? LOW : HIGH;
  digitalWrite(group01, group01State);
}

// Change the state of Group 02 Function Indicators
void group02Blink() {
  group02State = (group02State == HIGH) ? LOW : HIGH;
  digitalWrite(group02, group02State);
}

// Change the state of Group 03 Function Indicators
void group03Blink() {
  group03State = (group03State == HIGH) ? LOW : HIGH;
  digitalWrite(group03, group03State);
}

// Change the state of Group 04 Function Indicators
void group04Blink() {
  group04State = (group04State == HIGH) ? LOW : HIGH;
  digitalWrite(group04, group04State);
}

// Change the state of Sensor Indicator 01
void sensorInd01Blink() {
  sensorInd01State = (sensorInd01State == HIGH) ? LOW : HIGH;
  digitalWrite(sensorInd01, sensorInd01State);
}

// Change the state of Sensor Indicator 02
void sensorInd02Blink() {
  sensorInd02State = (sensorInd02State == HIGH) ? LOW : HIGH;
  digitalWrite(sensorInd02, sensorInd02State);
}           
        


Explanation of the code

This video is best viewed in full screen mode.

RETURN TO TOP OF PAGE


SOUND INDICATOR - MAKING THE ROBOT MOUTH LIGHT WITH HIS VOICE PATTERN

I cannot take credit for the original design or program code that I show with the Yellow LED's. The idea came from: Science Buddies - How to Use a Microphone with Arduino (Lesson #12)

However, I made modification to the circuit and the program code replace the individual LED's with an Adafruit Neo-Pixels 7-LED Jewel. I "think" the Neo-Pixels Jewel will work better behind the robot mouth.

Schematic Diagram

Here is the schematic diagrams for the two versions. I used an Arduino Uno for the circuit using the individual LED's an an Arduino Micro for the circuit using the Adafruit Neo-Pixels Jewel. These circuits should work on any Arduino board. Just make sure the Neo-Pixels Jewel uses a Pulse Width Modulated (PWM) output pin. The schematic was created using EasyEDA.

Bill of Material (BOM) - Individual LEDs

Prices are as of March 11, 2024

Quantity Description Part Number Vendor ASIN Number Price Per Extended Price
1 Arduino Uno REV3 (or similar) [A000066] Amazon B008GRTSV6 $24.50 $24.50
5 LED, 5mm Defused
Pack - 5 LEDs each
in 5 colors
25-pack
4203 Adafruit.com N/A $0.198 $4.95
5 E-Project #A-0004-B06 100 pcs Carbon Film
Resistors, 1/4W, 330Ω 5%
Amazon B0185F1D32 $0.07 $6.69
10 Male-to-Male wire jumpers
Set of 130pcs 12, 16, 20, 25cm
Only 3 wires required for this project
41383 Amazon B016KI622U $0.06 per wire $0.18

Bill of Material (BOM) - Adafruit Neo-Pixels Jewel

Prices are as of June 11, 2024

Quantity Description Part Number Vendor ASIN Number Price Per Extended Price
1 Arduino Micro with headers
(or similar)
[A000053] Amazon B00AFY2556 $27.48 $27.48
1 Electret Microphone
Amplifier Module MAX4466
Adjustable Gain Blue
Breakout Board for Arduino
Package of Six(6)
MAX4466 Amazon.com B08LD9C7WX $1.67 $9.99
1 NeoPixels Jewel
7 x 5050 RGB LED
with integrated drivers
2226 Adafruit.com N/A $5.95 $5.95

Program Code Used to Test Visual Voice Indication

The code in the following window can be selected, copied and pasted directly into your IDE. It should work well on a Windows or Mac. Simply place your mouse cursor where you want to start copying and then click and drag to select the text. Then copy the selection and paste it into your Integrated Development Environment (IDE).

Program code I modified from Science Buddies to produce a visual audio indicator using individual LEDs to be used for the B9 robot mouth.

// Microphone test for audio level blinking
// February 15, 2024
// Modified By: John G. Todora, Jr.
            
// Science Buddies
// Reference: https://www.youtube.com/watch?v=bMs5J4bJOD0
            
#define mic A0
#define led01 3
#define led02 4
#define led03 5
#define led04 6
#define led05 7
            
int delta = 0;          // Will be used to set threshold steps
int maxAmplitude = 300; // Guess as to the maximum amplitude the mic will see
int amplitude = 0;      // Variable to store the actual amplitude of the mice
            
/* The microphone is best powered with the 3.3V supply. This is according 
   to the microphone specification sheet. The microphone output will be 
   connected to an analog input pin of an Arduino. The analog pin(s) on 
   the Arduino produce a count of 1023 based on a 5.0V signal, since I'll 
   be using 3.3V the count will be: 3.3V * 1023 / 5 = 675 counts. The 
   microphone has a DC offset of approximately 1.55V. That means that zero (0)
   volts is not silence and 3.3V is not maximum volume, but that 1.55V is 
   silence and the audio will be positive and negative, therefore; the 
   positive half will have a count of 337 counts and the negative half will 
   have a count of 337 counts. This means that to get the amplitude, I'll 
   have to take the absolute value (ABS).
            
   Based on this the baseline, or silence, will be 337 counts and therefore 
   a variable named: baseline is declared and assigned the value of 337.
*/
int baseline = 337;
            
/* The program will be using five LED's to display sound level, acting 
   like a VU meter in a recording studion. Get set a level or threshold 
   for when each LED lights a variable is created named: numOfLEDs to 
   set the number of LEDs that will be used to display the sound level.
*/
int numOfLEDs = 5;
            
// Five variable will be needed to store the different threshold values.
int threshHold01 = 0;
int threshHold02 = 0;
int threshHold03 = 0;
int threshHold04 = 0;
int threshHold05 = 0;
           
void setup() {
    Serial.begin(9600);
            
    pinMode(mic, INPUT);
    pinMode(led01, OUTPUT);
    pinMode(led02, OUTPUT);
    pinMode(led03, OUTPUT);
    pinMode(led04, OUTPUT);
    pinMode(led05, OUTPUT);
}
            
void loop() {
    // The delta or step size of the threshold is calculated
    delta = maxAmplitude / (numOfLEDs);
              
    // Each threshold value is set
    threshHold01 = delta;
    threshHold02 = threshHold01 + delta;
    threshHold03 = threshHold02 + delta;
    threshHold04 = threshHold03 + delta;
    threshHold05 = threshHold04 + delta;
         
    // Calculate the amplitude of the audio signal
    amplitude = abs(analogRead(mic) - baseline);
    Serial.print("mic value = ");
    Serial.println(amplitude);
         
    // Display the amplitude on the LED's
    if (amplitude < threshHold01) {
        digitalWrite(led01, LOW);
        digitalWrite(led02, LOW);
        digitalWrite(led03, LOW);
        digitalWrite(led04, LOW);
        digitalWrite(led05, LOW);
    }
    if (amplitude > threshHold01) {
        digitalWrite(led01, HIGH);
        digitalWrite(led02, LOW);
        digitalWrite(led03, LOW);
        digitalWrite(led04, LOW);
        digitalWrite(led05, LOW);
    }
    if (amplitude > threshHold02) {
        digitalWrite(led01, HIGH);
        digitalWrite(led02, HIGH);
        digitalWrite(led03, LOW);
        digitalWrite(led04, LOW);
        digitalWrite(led05, LOW);
    }
    if (amplitude > threshHold03) {
        digitalWrite(led01, HIGH);
        digitalWrite(led02, HIGH);
        digitalWrite(led03, HIGH);
        digitalWrite(led04, LOW);
        digitalWrite(led05, LOW);
    }
    if (amplitude > threshHold04) {
        digitalWrite(led01, HIGH);
        digitalWrite(led02, HIGH);
        digitalWrite(led03, HIGH);
        digitalWrite(led04, HIGH);
        digitalWrite(led05, LOW);
    }
    if (amplitude > threshHold05) {
        digitalWrite(led01, HIGH);
        digitalWrite(led02, HIGH);
        digitalWrite(led03, HIGH);
        digitalWrite(led04, HIGH);
        digitalWrite(led05, HIGH);
    }
            
}
        


Sound Visual Monitor Using Individual LEDs

This video is best viewed in full screen mode.



Explanation of the code

This video is best viewed in full screen mode.





The program code for using a Neo-Pixels Jewel is similar to the code used for individual LEDs; however, the Adafruit Neo-Pixels Library is needed and the method used to control the individual LEDs is different.

// Experimenting with NeoPixel as sound VU
// Filename: experimenting_pixel_vu.ino
// Code Modified by: John G. (Skip) Todora, Jr.
// Date: June 5, 2024
            
// Science Buddies - Source of original concept and code
// Reference: https://www.youtube.com/watch?v=bMs5J4bJOD0
            
// Science Buddies used individual LED's for the VU meter
// I modified the program to use a NeoPixels 7-LED Pixels
            
#include   // Include the library for the Adafruit Pixels
            
#define pixelLedCount 7         // Define the number of LED's on the Pixels
#define pixelLedPin 10          // Define the output pin of the Pixels
#define mic A0                  // Define the analog input of the microphone
            
// Create a NewPixel object
Adafruit_NeoPixel soundMonitor(pixelLedCount, pixelLedPin, NEO_GRB + NEO_KHZ800);
            
// Define the LED color of the Pixels
#define COLOR_RED soundMonitor.Color(255,0,0)
            
/* 
   According to the microphone specification sheet, when wiring the microphone 
   to an Arduino, it is best powered with from the Arduino 3.3V supply. This 
   will aid in reducing the power supply noise level that could be present. 
   The microphone output will be connected to an analog input pin of an 
   Arduino. The analog pin(s) on the Arduino produce a count of 0 to 1023 
   based on a 5.0V signal, since I'll be using 3.3V, the count will be: 
   3.3V * 1023 / 5 = 675 counts, therefore a count will be produced in the 
   range of 0 to 675 counts. The microphone has a DC offset of ~1.6V, half of 
   the 3.3V. That means zero (0) volts will not represent silence, but   
   silence will be ~1.6V which will produce a count value of ~337. That said, 
   a count value of ~337 represents silence. The audio will be positive and 
   negative above and below the offset, therefore; the positive half will 
   have a count of 337 + 337 = 674 counts and the negative half will have a 
   count of 337 - 337 = 0 counts. Therefore, the audio will vary 337 counts 
   above and below the baseline of 337 counts. Because math will be used 
   to calculate the amplitude of the audio, I'll have to take the absolute 
   value (ABS) so there will be no negative numbers.
            
   Based on this the baseline, or silence, will be 337 counts and therefore 
   a variable named: baseline is declared and assigned the value of 337.
*/
            
int baseLine = 337;       // Counts that represent silence
int delta = 0;            // Variable to store the different audio levels
int maxAmplitude = 334;   // Counts that represent maximum audio level
int amplitude = 0;        // Variable to store the calculated amplitude
            
// To make the LEDs blink at different audio levels, we need to set up levels 
// for when each LED of the Pixels will turn on or off
// The LED's of the Pixels are numbered starting with zero (0) therefore; 
// seven (7) LED's are numbered 0 through 6
int level00 = 0;
int level01 = 0;
int level02 = 0;
int level03 = 0;
int level04 = 0;
int level05 = 0;
int level06 = 0;
int level07 = 0;
            
// Setup function runs once at startup
void setup() {
    Serial.begin(9600);                           // Initialize the Serial port if needed
            
    pinMode(mic, INPUT);                          // Set the mode of the analog pin
            
    delta = maxAmplitude / (pixelLedCount + 1);   // Calculate the level for each LED of the Pixels
            
    // Calculate the levels for each LED of the Pixels to turn on/off
    level00 = delta;
    level01 = level00 + delta;
    level02 = level01 + delta;
    level03 = level02 + delta;
    level04 = level03 + delta;
    level05 = level04 + delta;
    level06 = level05 + delta;
    level07 = level06 + delta;
            
    // Call function to initialize the NeoPixels Pixels
    initPixels();
}
            
void loop() {
    // Calculate the amplitude of the microphone signal
    amplitude = abs(analogRead(mic) - baseLine);
            
    // Use the amplitude and test against the levels calculated to turn on/off
    // the appropriate LED's of the Pixels.
    if (amplitude < level00) {
        soundMonitor.clear();
        soundMonitor.show();
    }
            
    if (amplitude > level01) {
        soundMonitor.clear();
        soundMonitor.setPixelColor(0, COLOR_RED);
        // soundMonitor.setPixelColor(1, COLOR_RED);
        soundMonitor.show();
    }
            
    if (amplitude > level02) {
        soundMonitor.clear();
        soundMonitor.setPixelColor(0, COLOR_RED);
        soundMonitor.setPixelColor(1, COLOR_RED);
        // soundMonitor.setPixelColor(2, COLOR_RED);
        soundMonitor.show();
    }
            
    if (amplitude > level03) {
        soundMonitor.clear();
        soundMonitor.setPixelColor(0, COLOR_RED);
        soundMonitor.setPixelColor(1, COLOR_RED);
        soundMonitor.setPixelColor(2, COLOR_RED);
        // soundMonitor.setPixelColor(3, COLOR_RED);
        soundMonitor.show();
    }
            
    if (amplitude > level04) {
        soundMonitor.clear();
        soundMonitor.setPixelColor(0, COLOR_RED);
        soundMonitor.setPixelColor(1, COLOR_RED);
        soundMonitor.setPixelColor(2, COLOR_RED);
        soundMonitor.setPixelColor(3, COLOR_RED);
        // soundMonitor.setPixelColor(4, COLOR_RED);
        soundMonitor.show();
    }
            
    if (amplitude > level05) {
        soundMonitor.clear();
        soundMonitor.setPixelColor(0, COLOR_RED);
        soundMonitor.setPixelColor(1, COLOR_RED);
        soundMonitor.setPixelColor(2, COLOR_RED);
        soundMonitor.setPixelColor(3, COLOR_RED);
        soundMonitor.setPixelColor(4, COLOR_RED);
        // soundMonitor.setPixelColor(5, COLOR_RED);
        soundMonitor.show();
    }
            
    if (amplitude > level06) {
        soundMonitor.clear();
        soundMonitor.setPixelColor(0, COLOR_RED);
        soundMonitor.setPixelColor(1, COLOR_RED);
        soundMonitor.setPixelColor(2, COLOR_RED);
        soundMonitor.setPixelColor(3, COLOR_RED);
        soundMonitor.setPixelColor(4, COLOR_RED);
        soundMonitor.setPixelColor(5, COLOR_RED);
        // soundMonitor.setPixelColor(6, COLOR_RED);
        soundMonitor.show();
    }
            
    if (amplitude > level07) {
        soundMonitor.clear();
        soundMonitor.setPixelColor(0, COLOR_RED);
        soundMonitor.setPixelColor(1, COLOR_RED);
        soundMonitor.setPixelColor(2, COLOR_RED);
        soundMonitor.setPixelColor(3, COLOR_RED);
        soundMonitor.setPixelColor(4, COLOR_RED);
        soundMonitor.setPixelColor(5, COLOR_RED);
        soundMonitor.setPixelColor(6, COLOR_RED);
        soundMonitor.show();
    }
}
            
// Function to initialize the NeoPixel Pixels
void initPixels(void) {
    soundMonitor.begin();
    soundMonitor.setBrightness(100);
    soundMonitor.clear();
    soundMonitor.show();
}
        


Sound Visual Monitor Using a Neo-Pixels Jewel

This video is best viewed in full screen mode.



Explanation of the code

This video is best viewed in full screen mode.



RETURN TO TOP OF PAGE


PRINTED CIRCUIT BOARD DESIGN FOR THE CHEST LIGHTS

The chest lights are divided into three sections as shown in the photo - Chest Light Identification. (Click the image to enlarge the image).

The Function Indicator holes are perfect to accept a 3mm LED. What I have to do is figure out a way to mount and wire them to use as little space as possible and to make it removable for future repairs. Yes...I'm from a generation of engineers who actually considers a design for not only functionality, but also for serviceability.

The Programming Switches are backlit. I've been looking for small push button switches; however, as of this writing (05/09/2025) have not found a suitable candidate. Therefore, I plant to use the clear lenses that come in the kit and back light them.

The Sensor Indicator holes are perfect to accept a 5mm LED. The colors of these two indicators varied depending on what season the B9 robot appears in.

The kit comes with a clear insert for the chest to fill the programming switch and the function indicator openings, as shown in the photo - Clear Plastic Chest Insert. (Click the image to enlarge the image).

I will not need the section of this clear insert that fills the function indicators because the 5mm LED's will protrude through those holes; however, I will be using the clear insert for the programming switches. Therefore, the insert will be cut where where shown in the photo. These rectangular areas will be back lit with 5mm LED's using a diffuser and a light guide tube to help with focus on each rectangle, but not to over power the clear rectangle.

The photo - Parts Used For Assembling Chest Indicators, shows the parts that will be used in my first attempt to back light the programming switches. (click the image to enlarge the image).

Notice that in this photo the clear chest insert has been cut as I showed in the previous photo. The plastic cup that has been cut will be used as a diffuser. The rectangular cut piece of the cup will be glued to the back of the clear programming switches insert. I than used Evergreen #226 (3/16" - 0.188" - 4.77mm) tube, cut to the length of the LED, to focus the LED light forward to to the clear insert. The length of the light guides is 6mm. I might need to increase the length of these tubes to more disperse the light so that it does not create a "hot spot" on the clear insert.

I used Elmer's Disappearing Purple Washable School Glue to glue the diffuser to the clear plastic Programming Switch insert.

I used Elmer's Disappearing Purple Washable School Glue to glue the diffuser to the clear plastic Programming Switch insert. I often use this glue in certain areas of my model builds in places where there is little to know stress and also need the glue to dry transparent.

Spoiler alert!...After letting the glue dry for 24-hours, which is much longer than required, I was happy that there wasn't a trace of glue showing. I started the assembly process of placing the LED's into the guides and aligning everything into the chest. This is when I found out the glue is not strong enough for this application because parts started falling off. Oh well...lesson learned.

I disassembled the assembly and cleaned all the glue residue from all surfaces. I then experimented with using Elmer's white glue.

RETURN TO TOP OF PAGE




Skip's Messy Workbench ⇔ All rights reserved ⇔ Copyright © 2023-2024
Skip's Messy Workbench ⇔ Last updated: March 09, 2024
Page Background Image by wirestock on Freepik

Valid HTML!
Valid CSS!