element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • About Us
  • Community Hub
    Community Hub
    • What's New on element14
    • Feedback and Support
    • Benefits of Membership
    • Personal Blogs
    • Members Area
    • Achievement Levels
  • Learn
    Learn
    • Ask an Expert
    • eBooks
    • element14 presents
    • Learning Center
    • Tech Spotlight
    • STEM Academy
    • Webinars, Training and Events
    • Learning Groups
  • Technologies
    Technologies
    • 3D Printing
    • FPGA
    • Industrial Automation
    • Internet of Things
    • Power & Energy
    • Sensors
    • Technology Groups
  • Challenges & Projects
    Challenges & Projects
    • Design Challenges
    • element14 presents Projects
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • Project Groups
  • Products
    Products
    • Arduino
    • Avnet Boards Community
    • Dev Tools
    • Manufacturers
    • Multicomp Pro
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • Store
    Store
    • Visit Your Store
    • Choose another store...
      • Europe
      •  Austria (German)
      •  Belgium (Dutch, French)
      •  Bulgaria (Bulgarian)
      •  Czech Republic (Czech)
      •  Denmark (Danish)
      •  Estonia (Estonian)
      •  Finland (Finnish)
      •  France (French)
      •  Germany (German)
      •  Hungary (Hungarian)
      •  Ireland
      •  Israel
      •  Italy (Italian)
      •  Latvia (Latvian)
      •  
      •  Lithuania (Lithuanian)
      •  Netherlands (Dutch)
      •  Norway (Norwegian)
      •  Poland (Polish)
      •  Portugal (Portuguese)
      •  Romania (Romanian)
      •  Russia (Russian)
      •  Slovakia (Slovak)
      •  Slovenia (Slovenian)
      •  Spain (Spanish)
      •  Sweden (Swedish)
      •  Switzerland(German, French)
      •  Turkey (Turkish)
      •  United Kingdom
      • Asia Pacific
      •  Australia
      •  China
      •  Hong Kong
      •  India
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      • Americas
      •  Brazil (Portuguese)
      •  Canada
      •  Mexico (Spanish)
      •  United States
      Can't find the country/region you're looking for? Visit our export site or find a local distributor.
  • Translate
  • Profile
  • Settings
Twist, Turn and Move Design Challenge with TE Robotics
  • Challenges & Projects
  • Design Challenges
  • Twist, Turn and Move Design Challenge with TE Robotics
  • More
  • Cancel
Twist, Turn and Move Design Challenge with TE Robotics
Blog Sammy Semaphore Fully Functioning - Blog 7
  • Blog
  • Forum
  • Documents
  • Polls
  • Files
  • Leaderboard
  • Mentions
  • Sub-Groups
  • Tags
  • More
  • Cancel
  • New
  • Share
  • More
  • Cancel
Group Actions
  • Group RSS
  • More
  • Cancel
Engagement
  • Author Author: dougw
  • Date Created: 13 Sep 2022 3:44 AM Date Created
  • Views 2504 views
  • Likes 17 likes
  • Comments 18 comments
  • dougw
  • doug wong
  • Sammy Semaphore
  • Twist Turn and Move Robotics Design Challenge
Related
Recommended

Sammy Semaphore Fully Functioning - Blog 7

dougw
dougw
13 Sep 2022

Intro

Sammy Semaphore is finally fully functional, complete with remote Bluetooth control. He turned out very well, although not without having to work through adversity. The biggest issues were supply chain and the fact that I got very sick.

Sammy Semaphore Signaling His Alphabet

You don't have permission to edit metadata of this video.
Edit media
x
image
Upload Preview
image

Alphabet Firmware

//Sammy Semaphore
//the semaphore alphabet is enacted at the same time as the display shows the corresponding character
//Arduino UNO, 8x8 NEO pixel display, dual servo motors, Bluetooth
//This demo displays the whole semaphore alphabet
//by Doug Wong 2022

#include <FastLED.h>
#define NLEDS 64 
#define LEDpin 2
#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>

CRGB leds[NLEDS];

Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();

#define SERVOMIN  50 // This is the 'minimum' pulse length count (out of 4096)
#define SERVOMAX  700 // This is the 'maximum' pulse length count (out of 4096)
#define SERVO_FREQ 50 // Analog servos run at ~50 Hz updates

// Servo values for 6 arm positions
uint16_t RS[6] = {83, 170, 269, 380, 455, 495};
uint16_t LS[6] = {480, 380, 294, 180, 106, 70};
//uint16_t RS[6] = {50, 175, 300, 475, 650, 700};
//uint16_t LS[6] = {700, 650, 475, 300, 175, 50};

uint16_t Rx = 50;   //
uint16_t Lx = 700;  //
uint16_t RC = 50;  //right target
uint16_t RT = 50;  //right current
uint16_t LC = 50;  //left target
uint16_t LT = 50;  //left current

// LED font for 8x8 pixels
byte AL[28][8] = {
{129, 129, 129, 255, 129, 129, 66, 60},     //A0
{127, 129, 129, 129, 127, 129, 129, 127},   //B1
{124,  130, 1, 1, 1, 1, 130, 124},          //C2
{63, 65, 129, 129, 129, 129, 65, 63},       //D3
{255, 1, 1, 1, 63, 1, 1, 255},              //E4
{1, 1, 1, 1, 63, 1, 1, 255},                //F5
{124, 130, 129, 225, 1, 1, 130, 124},       //G6
{129, 129, 129, 129, 255, 129, 129, 129},   //H7
{28, 8, 8, 8, 8, 8, 8, 28},                 //I8
{30, 33, 33, 32, 32, 32, 32, 248},          //J9
{129, 65, 33, 17, 31, 33, 65, 129},         //K10
{255, 129, 1, 1, 1, 1, 1, 1},               //L11
{129, 129, 129, 129, 153, 165, 195, 129},   //M12
{129, 193, 161, 145, 145, 137, 133, 131},   //N13
{126, 129, 129, 129, 129, 129, 129, 126},   //O14
{1, 1, 1, 1, 127, 129, 129, 127},           //P15
{190, 65, 161, 129, 129, 129, 129, 126},    //Q16
{129, 65, 33, 127, 129, 129, 129, 127},     //R17
{126, 129, 128, 64, 62, 1, 129, 126},       //S18
{8, 8, 8, 8, 8, 8, 8, 127},                 //T19
{126, 129, 129, 129, 129, 129, 129, 129},   //U20
{24, 36, 36, 66, 66, 129, 129, 129},        //V21
{129, 195, 165, 153, 129, 129, 129, 129},   //W22
{129, 66, 36, 24, 24, 36, 66, 129},         //X23
{16, 16, 16, 16, 24, 36, 66, 129},          //Y24
{255, 2, 4, 8, 16, 32, 64, 255},            //Z25
{255, 0, 0, 0, 0, 0, 0, 0},                 //[space26
{36, 36, 255, 36, 36, 255, 36, 36}          //\#
};

//flag positions corresponding to each letter
//                   A  B  C  D  E  F  G  H  I  J  K  L  M  N  O  P  Q  R  S  T  U  V  W  X  Y  Z SP  #
uint16_t rpos[28] = {0, 0, 0, 0, 3, 2, 1, 0, 5, 2, 4, 3, 2, 1, 5, 4, 3, 2, 1, 4, 3, 1, 2, 1, 2, 2, 0, 3}; 
uint16_t lpos[28] = {1, 2, 3, 4, 0, 0, 0, 2, 1, 4, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 4, 5, 5, 3, 0, 0, 4}; 

char charac;
char space = " ";
char nn = "#";
char ABC[29] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ # ";

// servo # setup 
uint8_t servo1 = 0;
uint8_t servo2 = 1;


void setup() {

  Serial.begin(9600);

  pwm.begin();
  pwm.setOscillatorFrequency(27000000);
  pwm.setPWMFreq(SERVO_FREQ);  // Analog servos run at ~50 Hz updates

  FastLED.addLeds<WS2812B, LEDpin, GRB>(leds, NLEDS);
  FastLED.setBrightness(50);

}

void loop()
{
  for (int i = 0; i < 26; i++) {
  charac = ABC[i];
//  Serial.println(charac);
  Mchar (charac, i);
  }
  charac = ABC[26];
//  Serial.println(charac);
  Mchar (charac, 26);
  charac = ABC[27];
  Mchar (charac, 27);
}

void Mchar(char Charac, int ic) {
    uint16_t rc, lc, tc;
    uint16_t ichar;
    ichar = int(Charac);           //convert to integer
    if (ichar == 32) ichar = 91;   //space
    if (ichar == 35) ichar = 92;   //#
    ichar = ichar - 65;             //set index to 0
    tc = rpos[ichar];
    rc = RS[tc];                   //get right flag position PWM value
    tc = lpos[ichar];
    lc = LS[tc];                   //get left flag position PWM value
    pwm.setPWM(servo1, 0, rc);
    pwm.setPWM(servo2, 0, lc);
    BlankDisplay();
    delay(100);
    DisplayChar(ichar);
    delay(1500);  
}

void DisplayChar(int abc){
  int rc, cc;
  for (rc = 0; rc < 8; rc++)
  {
    for (cc = 0; cc < 8; cc++)
    {
       if (bitRead(AL[abc][rc], cc) == 1)
       {
        leds[rc + cc * 8] = CRGB::Green;
       }
       else
       {
        leds[rc + cc * 8] = CRGB::Black;
       }
    }
  }
    FastLED.show();
}

void BlankDisplay()
{
    for (int ac = 0; ac < 64; ac++)
    {
      leds[ac] = CRGB::Black;
    }
    FastLED.show();
}

void rmove(uint16_t rc, uint16_t rt) {
if (rt > rc)
  for (uint16_t pulselen = RC; pulselen < RT; pulselen++) {
    pwm.setPWM(servo1, 0, pulselen);
    delay(5);
  }
  else
  for (uint16_t pulselen = RC; pulselen < RT; pulselen--) {
    pwm.setPWM(servo1, 0, pulselen);
    delay(5);
  }
  delay(1000);
}

void lmove(uint16_t lc, uint16_t lt) {
if (lt > lc)
  for (uint16_t pulselen = LC; pulselen < LT; pulselen++) {
    pwm.setPWM(servo1, 0, pulselen);
    delay(2);
  }
  else
  for (uint16_t pulselen = LC; pulselen < LT; pulselen--) {
    pwm.setPWM(servo1, 0, pulselen);
    delay(2);
  }
}

Sammy Semaphore Signaling Remotely Via Bluetooth

You don't have permission to edit metadata of this video.
Edit media
x
image
Upload Preview
image

Bluetooth Semaphore Firmware

//Sammy Semaphore
//semaphore signals can be controlled via Bluetooth - letters are displayed as both semaphores and corresponding characters
//Arduino UNO, 8x8 NEO pixel display, dual servo motors, Bluetooth
//by Doug Wong 2022

#include <FastLED.h>
#define NLEDS 64 
#define LEDpin 2
#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>

CRGB leds[NLEDS];

Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();

#define SERVOMIN  50 // This is the 'minimum' pulse length count (out of 4096)
#define SERVOMAX  700 // This is the 'maximum' pulse length count (out of 4096)
#define SERVO_FREQ 50 // Analog servos run at ~50 Hz updates

// Servo values for 6 arm positions
uint16_t RS[6] = {83, 170, 269, 380, 455, 495};
uint16_t LS[6] = {480, 380, 294, 180, 106, 70};
//uint16_t RS[6] = {50, 175, 300, 475, 650, 700};
//uint16_t LS[6] = {700, 650, 475, 300, 175, 50};

uint16_t Rx = 50;   //
uint16_t Lx = 700;  //
uint16_t RC = 50;  //right target
uint16_t RT = 50;  //right current
uint16_t LC = 50;  //left target
uint16_t LT = 50;  //left current

// LED font for 8x8 pixels
byte AL[28][8] = {
{129, 129, 129, 255, 129, 129, 66, 60},     //A0
{127, 129, 129, 129, 127, 129, 129, 127},   //B1
{124,  130, 1, 1, 1, 1, 130, 124},          //C2
{63, 65, 129, 129, 129, 129, 65, 63},       //D3
{255, 1, 1, 1, 63, 1, 1, 255},              //E4
{1, 1, 1, 1, 63, 1, 1, 255},                //F5
{124, 130, 129, 225, 1, 1, 130, 124},       //G6
{129, 129, 129, 129, 255, 129, 129, 129},   //H7
{28, 8, 8, 8, 8, 8, 8, 28},                 //I8
{30, 33, 33, 32, 32, 32, 32, 248},          //J9
{129, 65, 33, 17, 31, 33, 65, 129},         //K10
{255, 129, 1, 1, 1, 1, 1, 1},               //L11
{129, 129, 129, 129, 153, 165, 195, 129},   //M12
{129, 193, 161, 145, 145, 137, 133, 131},   //N13
{126, 129, 129, 129, 129, 129, 129, 126},   //O14
{1, 1, 1, 1, 127, 129, 129, 127},           //P15
{190, 65, 161, 129, 129, 129, 129, 126},    //Q16
{129, 65, 33, 127, 129, 129, 129, 127},     //R17
{126, 129, 128, 64, 62, 1, 129, 126},       //S18
{8, 8, 8, 8, 8, 8, 8, 127},                 //T19
{126, 129, 129, 129, 129, 129, 129, 129},   //U20
{24, 36, 36, 66, 66, 129, 129, 129},        //V21
{129, 195, 165, 153, 129, 129, 129, 129},   //W22
{129, 66, 36, 24, 24, 36, 66, 129},         //X23
{16, 16, 16, 16, 24, 36, 66, 129},          //Y24
{255, 2, 4, 8, 16, 32, 64, 255},            //Z25
{255, 0, 0, 0, 0, 0, 0, 0},                 //[space26
{36, 36, 255, 36, 36, 255, 36, 36}          //\#
};

//flag positions corresponding to each letter
//                   A  B  C  D  E  F  G  H  I  J  K  L  M  N  O  P  Q  R  S  T  U  V  W  X  Y  Z SP  #
uint16_t rpos[28] = {0, 0, 0, 0, 3, 2, 1, 0, 5, 2, 4, 3, 2, 1, 5, 4, 3, 2, 1, 4, 3, 1, 2, 1, 2, 2, 0, 3}; 
uint16_t lpos[28] = {1, 2, 3, 4, 0, 0, 0, 2, 1, 4, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 4, 5, 5, 3, 0, 0, 4}; 

char charac = "A";
char space = " ";
char nn = "#";
char ABC[29] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ # ";
char inputByte;
uint16_t ichr;

// servo # setup 
uint8_t servo1 = 0;
uint8_t servo2 = 1;


void setup() {

  Serial.begin(9600);

  pwm.begin(); 
  pwm.setOscillatorFrequency(27000000);
  pwm.setPWMFreq(SERVO_FREQ);  // Analog servos run at ~50 Hz updates

  FastLED.addLeds<WS2812B, LEDpin, GRB>(leds, NLEDS);
  FastLED.setBrightness(50);

}

void loop()
{
  while(Serial.available()>0){
  inputByte = Serial.read();
  Serial.println(inputByte);
  ichr = int(inputByte);
  if (ichr == 32) ichr = 91;   //space
  if (ichr == 35) ichr = 92;   //#
  ichr = ichr - 65;            //set index to 0
  if (ichr < 0) ichr = 26;
  if (ichr < 28){
  Serial.println(ichr);
  charac = ABC[ichr];
  Mchar (charac);
  }
}
}

void Mchar(char Charac) {
    uint16_t rc, lc, tc;
    uint16_t ichar;
    ichar = int(Charac);           //convert to integer
    if (ichar == 32) ichar = 91;   //space
    if (ichar == 35) ichar = 92;   //#
    ichar = ichar - 65;             //set index to 0
    tc = rpos[ichar];
    rc = RS[tc];                   //get right flag position PWM value
    tc = lpos[ichar];
    lc = LS[tc];                   //get left flag position PWM value
    pwm.setPWM(servo1, 0, rc);
    pwm.setPWM(servo2, 0, lc);
    BlankDisplay();
    delay(100);
    DisplayChar(ichar);
    delay(1500);  
}

void DisplayChar(int abc){
  int rc, cc;
  for (rc = 0; rc < 8; rc++)
  {
    for (cc = 0; cc < 8; cc++)
    {
       if (bitRead(AL[abc][rc], cc) == 1)
       {
        leds[rc + cc * 8] = CRGB::Green;
       }
       else
       {
        leds[rc + cc * 8] = CRGB::Black;
       }
    }
  }
    FastLED.show();
}

void BlankDisplay()
{
    for (int ac = 0; ac < 64; ac++)
    {
      leds[ac] = CRGB::Black;
    }
    FastLED.show();
}

void rmove(uint16_t rc, uint16_t rt) {
if (rt > rc)
  for (uint16_t pulselen = RC; pulselen < RT; pulselen++) {
    pwm.setPWM(servo1, 0, pulselen);
    delay(5);
  }
  else
  for (uint16_t pulselen = RC; pulselen < RT; pulselen--) {
    pwm.setPWM(servo1, 0, pulselen);
    delay(5);
  }
  delay(1000);
}

void lmove(uint16_t lc, uint16_t lt) {
if (lt > lc)
  for (uint16_t pulselen = LC; pulselen < LT; pulselen++) {
    pwm.setPWM(servo1, 0, pulselen);
    delay(2);
  }
  else
  for (uint16_t pulselen = LC; pulselen < LT; pulselen--) {
    pwm.setPWM(servo1, 0, pulselen);
    delay(2);
  }
}

Here is Sammy Semaphore Meets Nugget the Cat

You don't have permission to edit metadata of this video.
Edit media
x
image
Upload Preview
image

Discussion For Blog 7

This project was a tester - with all kinds of supply chain issues and dealing with sickness. Overall I am satisfied with my effort, but not so much with the results.

Supply Chain Issues:

  • I had many problems trying to acquire a complete set of TE Connectivity connectors.
    • some orders were cancelled after they were accepted due to lack of stock
    • my crimper could not do a great job on the pins in the kit
  • The fact that my PCBs did not arrive, was quite depressing
  • The servo motors that I ordered specially for this application were not the ones that arrived - so they had to be re-ordered and did not arrive in time

Sickness issues

Well I don't want to talk about getting Covid - it is just really painful to try and make progress when you are very sick.

What went well:

The Connector Tester design was interesting, including both the circuit design and the cycling mechanism. The PCBs are fairly simple so there is high confidence they will work. The design of Sammy Semaphore worked out well, it involved a lot of design and 3D printing, but I am very happy with the results, He manages to do a pretty good job even though he still does not have the correct motors.

What would I do differently?

I wouldn't get sick. Maybe I could expedite the PCB delivery. I might come up with a better way to tune servo positions. (it took a long time to sort out, partly because these servos work way better at 6V than 5 V.) I would learn C better (it is still a struggle that costs me time) I would blog more about the build steps, getting sick really curtailed what I could manage.

Conclusions

Some projects are going to un into adversity. We just need to fight through it and learn what we can from it. Although the connector tester part of the project did not go well, I did get to showcase building some really fabulous connectors. I am happy that at least the Sammy Semaphore part of the project was successful - it sometimes pays to have multiple irons in the fire. The project involved designing 2 systems, 2 PCBs, twelve 3-D printed parts, 5 firmware programs, 11 videos, several animations, and building half a dozen cables. Any project where I get to design some PCBs, design some mechanical mechanisms and make a system work, is a good project.

Thank you element14 and TE Connectivity for the opportunity to participate in this challenge. I learned a lot about semaphores and connectors.

Relevant Links:

Twist, Turn and Move Design Challenge with TE Robotics
Sammy Semaphore - blog 1
Connector Tester - blog 2
NEO Pixel Display - blog 3
Sammy Semaphore Torso Demo - Blog 4
I Am Sam I Am - Blog 5
TE Connectivity Connector Tester Blog 6
Sammy Semaphore Fully Functional Blog 7

The finisher prize

  • Sign in to reply

Top Comments

  • beacon_dave
    beacon_dave over 3 years ago +1
    Sammy is looking good and really busting those moves. However I can see a potential issue down at the local disco "Young man..."
Parents
  • maxpowerr
    maxpowerr over 3 years ago

    At this rate, you will soon overtake Boston Dynamics)))

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • dougw
    dougw over 3 years ago in reply to maxpowerr

    Relaxed Sammy is going in the other direction from Boston Dynamics - I don't think they will be using semaphores to communicate any time soon.Relaxed

    Although they do have some nice dance moves.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
Comment
  • dougw
    dougw over 3 years ago in reply to maxpowerr

    Relaxed Sammy is going in the other direction from Boston Dynamics - I don't think they will be using semaphores to communicate any time soon.Relaxed

    Although they do have some nice dance moves.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
Children
No Data
element14 Community

element14 is the first online community specifically for engineers. Connect with your peers and get expert answers to your questions.

  • Members
  • Learn
  • Technologies
  • Challenges & Projects
  • Products
  • Store
  • About Us
  • Feedback & Support
  • FAQs
  • Terms of Use
  • Privacy Policy
  • Legal and Copyright Notices
  • Sitemap
  • Cookies

An Avnet Company © 2025 Premier Farnell Limited. All Rights Reserved.

Premier Farnell Ltd, registered in England and Wales (no 00876412), registered office: Farnell House, Forge Lane, Leeds LS12 2NE.

ICP 备案号 10220084.

Follow element14

  • X
  • Facebook
  • linkedin
  • YouTube