5.5 Jan-Ken Punch
5.5.1 Overview
In the Rock-paper-scissors game, we replace gestures with labels of 16h5, including 0(Rock), 1(Scissors) and 2(Paper), to compete with the car. The car will randomly generate 0(Rock), 1(Scissors) and 2(Paper). If the car wins, it will emit a green light and a victory sound. If the car loses, it will emit a red light and a defeat sound. If it’s a draw, the car will emit a blue light and a draw sound.
5.5.2 Code Flow

5.5.3 Test Code
#include <Arduino.h>
#include <Sentry.h>
#include <Adafruit_NeoPixel.h>
#define PIN A3
Adafruit_NeoPixel strip = Adafruit_NeoPixel(4, PIN, NEO_GRB + NEO_KHZ800);
typedef Sengo2 Sengo;
#define SENGO_I2C
// #define SENGO_UART
#ifdef SENGO_I2C
#include <Wire.h>
#endif
#ifdef SENGO_UART
#include <SoftwareSerial.h>
#define TX_PIN 11
#define RX_PIN 10
SoftwareSerial mySerial(RX_PIN, TX_PIN);
#endif
#define VISION_TYPE Sengo::kVisionAprilTag
Sengo sengo;
#define BUZZER_PIN 3
int left_speed = 255;
int right_speed = 255;
String gesture[3] = { "Rock", "Scissors", "Paper" };
void setup() {
sentry_err_t err = SENTRY_OK;
Serial.begin(9600);
Serial.println("Waiting for sengo initialize...");
#ifdef SENGO_I2C
Wire.begin();
while (SENTRY_OK != sengo.begin(&Wire)) {
yield();
}
#endif // SENGO_I2C
#ifdef SENGO_UART
mySerial.begin(9600);
while (SENTRY_OK != sengo.begin(&mySerial)) {
yield();
}
#endif // SENGO_UART
Serial.println("Sengo begin Success.");
err = sengo.VisionSetMode(VISION_TYPE, Sengo::kVisionModeFamily16H5);
err = sengo.VisionSetLevel(VISION_TYPE, kLevelSpeed);
if (err) {
Serial.print("sengo.VisionSetMode Error: 0x");
Serial.println(err, HEX);
}
err = sengo.VisionBegin(VISION_TYPE);
Serial.print("sengo.VisionBegin(kVisionAprilTag) ");
if (err) {
Serial.print("Error: 0x");
} else {
Serial.print("Success: 0x");
}
Serial.println(err, HEX);
pinMode(BUZZER_PIN, OUTPUT);
strip.begin();
strip.show(); // Initialize all pixels to 'off'
}
void loop() {
int randomNumber = random(3); // Randomly generate one of the numbers 0, 1 or 2
int result = 0;
int obj_num = sengo.GetValue(VISION_TYPE, kStatus);
if (obj_num) {
for (int i = 1; i <= obj_num; ++i) {
int userNumber = sengo.GetValue(VISION_TYPE, kLabel, i);
if (userNumber < 3) {
countdown(2);
playStartSound();
result = (userNumber - randomNumber + 3) % 3;
Serial.print("Robot picks:");
Serial.print(gesture[randomNumber]);
Serial.print(" You pick:");
Serial.print(gesture[userNumber]);
Serial.print(" Robot says:");
if (result == 0) {
Serial.println("Draw");
drawSound();
colorWipe(strip.Color(0, 0, 255), 50); // blue on
} else if (result == 1) {
Serial.println("I win!");
victorySound();
colorWipe(strip.Color(0, 255, 0), 50); // green on
} else if (result == 2) {
Serial.println("I lose!");
defeatSound();
colorWipe(strip.Color(255, 0, 0), 50); // red on
}
} else {
break;
}
}
}
}
// Fill the dots one after the other with a color
void colorWipe(uint32_t c, uint8_t wait) {
for (uint16_t i = 0; i < strip.numPixels(); i++) {
strip.setPixelColor(i, c);
strip.show();
delay(wait);
}
}
void countdown(int seconds) {
for (int i = seconds; i > 0; i--) {
// The ticking of the countdown
tone(BUZZER_PIN, 800, 100);
delay(200);
noTone(BUZZER_PIN);
// Interval time
delay(800);
}
}
void playStartSound() {
// The sound of the game starting - Ascending scale + ending note
tone(BUZZER_PIN, 523, 100); // C5
delay(120);
tone(BUZZER_PIN, 659, 100); // E5
delay(120);
tone(BUZZER_PIN, 784, 100); // G5
delay(120);
tone(BUZZER_PIN, 1046, 300); // C6 high
delay(350);
noTone(BUZZER_PIN);
}
void victorySound() {
// Victory: A light and brisk rhythm (tick - tick tick)
tone(BUZZER_PIN, 587, 150); // D5
delay(200);
tone(BUZZER_PIN, 784, 100); // G5
delay(120);
tone(BUZZER_PIN, 1046, 200); // C6
delay(250);
noTone(BUZZER_PIN);
}
void defeatSound() {
// Defeat: Slow double bass (beep... beep...)
tone(BUZZER_PIN, 220, 400); // A3
delay(500);
tone(BUZZER_PIN, 196, 600); // G3
delay(700);
noTone(BUZZER_PIN);
}
void drawSound() {
// Draw: Smooth trill
for (int i = 0; i < 3; i++) {
tone(BUZZER_PIN, 349, 80); // F4
delay(100);
tone(BUZZER_PIN, 330, 80); // E4
delay(100);
}
noTone(BUZZER_PIN);
}
5.5.4 Test Result
After uploading the code, the AI vision module will detect the captured image to determine if there is 16h5 label. If there is, the label value will be transmitted to the development board. We can randomly place the cards with label values of “0, 1, 2” in the camera recognition area to play Janken with the car. If it’s a draw, the car will emit a blue light and a draw sound. If the car wins, it will emit a green light and a victory sound. If the car loses, it will emit a red light and a defeat sound.