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
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.
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.
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.
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.
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.
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.
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 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 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.
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.
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 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 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.
SOUND INDICATOR - MAKING THE ROBOT MOUTH LIGHT WITH HIS VOICE PATTERN
THIS SECTION IS COMING SOON AS OF MARCH 17, 2024