Danni Fernandez
Published

Avnet E-Casino Chip

Learn how to assemble your Avnet electronic casino chip badge and how it was made on Fusion Electronics. This project will give you the win!

IntermediateFull instructions provided2 hours120
Avnet E-Casino Chip

Things used in this project

Hardware components

BAT-HLD-003-SMT
×1
VJ0805Y104MXATW1BC
×1
CRGCQ0805F68R
×3
FSM4JSMA
×1
STM32G031J6M6
×1
RGB LED (150141M173100)
×1
Butterfly clutch
×1
Avnet Casino Chip PCB - UV printing Multi-color
×1

Software apps and online services

Fusion
Autodesk Fusion
Arduino IDE
Arduino IDE
STM32CUBEPROG
STMicroelectronics STM32CUBEPROG

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)
Solder Wire, 40/60
Solder Wire, 40/60
Tweezers

Story

Read more

Schematics

Schematic - Avnet casino Chip

Schematic of the badge

Code

Avnet Casino Chip Badge

Arduino
Firmware for the STM32, don't forget to set NRST_MODE to option 2 (GPIO: standard GPIO pad functionality, only internal RESET posible) whn programming the first time. Needs to be done with STM32CubeProgrammer.
/*
 * =====================================================
 * AVNET BADGE 2026
 * =====================================================
 *
 * Author      : Danni Fernandez (dannimakes)
 * Project     : Avnet Casino Chip Badge
 * IDE         : STM32Core / Arduino
 *
 * Description:
 * RGB LED animation firmware for the Avnet Casino Chip
 * Badge. Includes casino-themed animations, button
 * controlled mode selection and low-power sleep/wake
 * functionality.
 *
 * =====================================================
 * BUILD REQUIREMENTS
 * =====================================================
 *
 * Required software:
 *   - Arduino IDE
 *   - STM32core for Arduino
 *
 * Required libraries:
 *   - STM32LowPower
 *   - STM32RTC (required by STM32LowPower)
 *
 * =====================================================
 * ARDUINO IDE CONFIGURATION
 * =====================================================
 *
 * Board:
 *   Generic STM32G0 series
 *
 * Board part number:
 *   Generic G031J6Mx
 *
 * Optimize:
 *   Smallest (-Os default)
 *
 * C Runtime Library:
 *   Newlib Nano (default)
 *
 * Upload method:
 *   STM32CubeProgrammer (SWD)
 *
 * USB support (if available):
 *   None
 *
 * U(S)ART support:
 *   Disabled (no Serial support)
 *
 * Debug symbols and core logs:
 *   None
 *
 * =====================================================
 * USER CONTROLS
 * =====================================================
 *
 * Short press:
 *   Advance to the next animation.
 *
 * Long press:
 *   Enter sleep mode / wake the badge.
 *
 * =====================================================
 * ANIMATION MODES
 * =====================================================
 *
 * 1  - $1 chip     : White
 * 2  - $5 chip     : Red
 * 3  - $25 chip    : Green
 * 4  - $100 chip   : Blue
 * 5  - $500 chip   : Purple
 * 6  - $1,000 chip : Yellow
 * 7  - Slot Machine
 * 8  - Avnet Party
 * 9  - Jackpot
 * 10 - Rainbow Vegas
 * 11 - RGB mystery
 * 12 - Demo (all of them in a cycle)
 *
 * =====================================================
 */

#include <STM32LowPower.h>

// Hardware:
// RGB LED: Common anode
#define PWM_R PB8
#define PWM_G PA0
#define PWM_B PB1
// Button: Active LOW with internal pull-up
#define BUTTON PA12

#define LONG_PRESS_MS 1500

const uint8_t TOTAL_ANIMATIONS = 12;

volatile bool wakeFlag = false;

uint8_t animationMode = 1;

bool buttonLast = HIGH;
uint32_t buttonPressTime = 0;

// Forward declarations
void handleButton();
void enterSleep();

// Wait helper for animations.
// It delays, checks the button, and exits the current animation if the mode changed.
#define WAIT(ms, mode) \
  do { \
    delay(ms); \
    handleButton(); \
    if (animationMode != mode) \
      return; \
  } while (0);


// =====================================================
// RGB MASTER FUNCTIONS
// =====================================================

void setLedBrightness(uint8_t pin, uint8_t percent) {
  if (percent > 100) percent = 100;

  // Common-anode LED adaptation:
  // 0% brightness = PWM 255 (off)
  // 100% brightness = PWM 20 (~92% of full LED drive)

  // Limiting the minimum PWM value from 0 to 20 reduces peak
  // current consumption with little to no visible loss in brightness,
  // helping extend CR2032 battery life.
  uint8_t pwm = map(percent, 0, 100, 255, 20);

  analogWrite(pin, pwm);
}

void setRGB(uint8_t r, uint8_t g, uint8_t b) {
  setLedBrightness(PWM_R, r);
  setLedBrightness(PWM_G, g);
  setLedBrightness(PWM_B, b);
}

void allOff() {
  setRGB(0, 0, 0);
}


// =====================================================
// SLEEP
// =====================================================

// Required wake callback.
void wakeupISR() {
  wakeFlag = true;
}

void enterSleep() {
  allOff();
  // This stops PWM hardware to save energy during sleep.
  digitalWrite(PWM_R, HIGH);
  digitalWrite(PWM_G, HIGH);
  digitalWrite(PWM_B, HIGH);

  // Wait for button release before going to sleep
  while (digitalRead(BUTTON) == LOW) {
    delay(10);
  }

  LowPower.attachInterruptWakeup(
    digitalPinToInterrupt(BUTTON),
    wakeupISR,
    FALLING);

  while (true) {
    LowPower.deepSleep();

    // The MCU woke up from a button press.
    // Confirm that the user keeps holding the button.
    uint32_t wakePressStart = millis();

    while (digitalRead(BUTTON) == LOW) {
      if ((millis() - wakePressStart) >= LONG_PRESS_MS) {
        // Wake confirmed with a long press
        setRGB(80, 80, 80);
        delay(200);
        allOff();
        delay(200);
        // Wait for button release
        while (digitalRead(BUTTON) == LOW) {
          delay(10);
        }

        wakeFlag = false;

        // Reset button state after wake
        buttonLast = HIGH;
        buttonPressTime = 0;

        return;
      }

      delay(5);
    }

    // Short press while sleeping:
    // go back to sleep immediately without turning the LED on.
    allOff();
  }
}


// =====================================================
// BUTTON
// =====================================================

void flashAnimationNumber(uint8_t mode) {
  uint8_t flashes = mode;

  for (uint8_t i = 0; i < flashes; i++) {  //flA
    setRGB(50, 50, 50);                    // White flash
    delay(100);

    allOff();
    delay(200);
  }

  delay(250);  // Small pause before animation starts
}

void handleButton() {
  bool current = digitalRead(BUTTON);

  // Button press detected
  if (buttonLast == HIGH && current == LOW) {
    buttonPressTime = millis();
  }

  // Button release detected
  if (buttonLast == LOW && current == HIGH) {
    uint32_t pressTime = millis() - buttonPressTime;

    // Short press changes animation
    if (pressTime < LONG_PRESS_MS) {
      animationMode++;
      allOff();
      delay(400);

      if (animationMode > TOTAL_ANIMATIONS) {
        animationMode = 1;
      }
      //flashAnimationNumber(animationMode); // uncoment if you want to blink same aoumt of times that animation number that is selected
    }
  }

  // Long press enters sleep mode
  if (current == LOW) {
    if ((millis() - buttonPressTime) >= LONG_PRESS_MS) {
      enterSleep();

      // Reset after returning from sleep
      buttonLast = HIGH;
      buttonPressTime = 0;

      return;
    }
  }

  buttonLast = current;
}


// =====================================================
// POKER CHIP ANIMATIONS
// Modes 1-6 represent chip denominations.
// The colors and mode assignments are unchanged.
// Each denomination has its own more elegant rhythm.
// =====================================================

// -----------------------------------------------------
// WHITE — $1
// Simple, calm breathing.
// -----------------------------------------------------

void animationChipWhite(uint8_t mode) {

  // Gentle fade in
  for (int i = 0; i <= 100; i += 2) {
    setRGB(i, i, i);
    WAIT(18, mode);
  }

  // Soft hold
  WAIT(180, mode);

  // Gentle fade out
  for (int i = 100; i >= 0; i -= 2) {
    setRGB(i, i, i);
    WAIT(18, mode);
  }

  allOff();
  WAIT(250, mode);
}


// -----------------------------------------------------
// RED — $5
// Two crisp pulses.
// -----------------------------------------------------

void animationChipRed(uint8_t mode) {

  // Two crisp, fast "snap" pulses.
  for (int pulse = 0; pulse < 2; pulse++) {

    for (int i = 0; i <= 100; i += 10) {
      setRGB(i, 0, 0);
      WAIT(5, mode);
    }

    WAIT(45, mode);

    for (int i = 100; i >= 15; i -= 10) {
      setRGB(i, 0, 0);
      WAIT(4, mode);
    }

    allOff();
    WAIT(70, mode);
  }

  WAIT(170, mode);
}


// -----------------------------------------------------
// GREEN — $25
// Three smooth pulses.
// -----------------------------------------------------

void animationChipGreen(uint8_t mode) {

  // Three smooth "bounce" pulses. Never fully snaps off.
  for (int pulse = 0; pulse < 3; pulse++) {

    for (int i = 20; i <= 100; i += 4) {
      setRGB(0, i, 0);
      WAIT(10, mode);
    }

    WAIT(55, mode);

    for (int i = 100; i >= 30; i -= 4) {
      setRGB(0, i, 0);
      WAIT(9, mode);
    }

    WAIT(35, mode);
  }

  for (int i = 30; i >= 0; i -= 3) {
    setRGB(0, i, 0);
    WAIT(10, mode);
  }

  allOff();
  WAIT(180, mode);
}


// -----------------------------------------------------
// BLUE — $100
// Four faster pulses with a clean finish.
// -----------------------------------------------------

void animationChipBlue(uint8_t mode) {

  for (int pulse = 0; pulse < 4; pulse++) {

    for (int i = 0; i <= 100; i += 5) {
      setRGB(0, 0, i);
      WAIT(8, mode);
    }

    WAIT(40, mode);

    for (int i = 100; i >= 15; i -= 5) {
      setRGB(0, 0, i);
      WAIT(7, mode);
    }

    allOff();
    WAIT(45, mode);
  }

  // Final blue accent
  setRGB(0, 0, 100);
  WAIT(100, mode);

  allOff();
  WAIT(180, mode);
}


// -----------------------------------------------------
// PURPLE — $500
// More elaborate double-pulse rhythm.
// -----------------------------------------------------

void animationChipPurple(uint8_t mode) {

  // First pair
  for (int pulse = 0; pulse < 2; pulse++) {

    for (int i = 0; i <= 100; i += 4) {
      setRGB(i, 0, (i * 90) / 100);
      WAIT(10, mode);
    }

    WAIT(50, mode);

    for (int i = 100; i >= 20; i -= 4) {
      setRGB(i, 0, (i * 90) / 100);
      WAIT(8, mode);
    }

    allOff();
    WAIT(50, mode);
  }

  // Brief pause gives the animation a deliberate "premium" rhythm
  WAIT(120, mode);

  // Final strong pulse
  for (int i = 0; i <= 100; i += 4) {
    setRGB(i, 0, (i * 90) / 100);
    WAIT(9, mode);
  }

  WAIT(100, mode);

  for (int i = 100; i >= 0; i -= 3) {
    setRGB(i, 0, (i * 90) / 100);
    WAIT(10, mode);
  }

  allOff();
  WAIT(220, mode);
}


// -----------------------------------------------------
// YELLOW — $1,000
// Slowest and most luxurious.
// Gold-like yellow breathing with a small highlight.
// -----------------------------------------------------

void animationChipYellow(uint8_t mode) {

  // Slow golden rise
  for (int i = 0; i <= 100; i += 2) {
    setRGB(
      (i * 80) / 100,
      (i * 60) / 100,
      0);

    WAIT(22, mode);
  }

  // Warm hold
  WAIT(220, mode);

  // Small highlight
  setRGB(100, 100, 20);
  WAIT(80, mode);

  setRGB(80, 60, 0);
  WAIT(100, mode);

  // Slow fade
  for (int i = 100; i >= 0; i -= 2) {
    setRGB(
      (i * 80) / 100,
      (i * 60) / 100,
      0);

    WAIT(22, mode);
  }

  allOff();
  WAIT(300, mode);
}

// =====================================================
// Additional animations
// Modes 7-12 to make the badge rock!
// =====================================================

// =====================================================
// MODE 7 - Slot Machine
// =====================================================

void animationSlotMachine(uint8_t mode) {
  const uint8_t colors[][3] = {
    { 100, 0, 0 }, { 100, 60, 0 }, { 100, 100, 0 }, { 0, 100, 0 }, { 0, 100, 100 }, { 0, 0, 100 }, { 100, 0, 100 }
  };

  const uint16_t spinDelay[] = {
    150, 120, 95, 75, 58, 45, 34, 25, 18
  };

  for (int speedStep = 0; speedStep < 9; speedStep++) {
    for (int c = 0; c < 7; c++) {
      setRGB(colors[c][0], colors[c][1], colors[c][2]);
      WAIT(spinDelay[speedStep], mode);
    }
  }

  // Brake
  for (int c = 0; c < 7; c++) {
    setRGB(colors[c][0], colors[c][1], colors[c][2]);
    WAIT(90, mode);
  }

  setRGB(100, 70, 5);
  WAIT(100, mode);

  allOff();
  WAIT(350, mode);

  // Jackpot hit
  for (int i = 0; i < 6; i++) {
    setRGB(100, 100, 100);
    WAIT(55, mode);
    allOff();
    WAIT(45, mode);
  }

  setRGB(100, 70, 5);
  WAIT(180, mode);

  setRGB(45, 30, 2);
  WAIT(100, mode);

  setRGB(100, 70, 5);
  WAIT(180, mode);

  allOff();
  WAIT(300, mode);
}


// -----------------------------------------------------
// MODE 8 — AVNET PARTY
// -----------------------------------------------------

void animationAvnetParty(uint8_t mode) {

  // Green-dominant opening
  for (int i = 0; i <= 100; i += 4) {
    setRGB(0, i, 0);
    WAIT(12, mode);
  }

  WAIT(120, mode);

  // Green breathing pulse
  for (int i = 100; i >= 25; i -= 4) {
    setRGB(0, i, 0);
    WAIT(10, mode);
  }

  for (int i = 25; i <= 100; i += 4) {
    setRGB(0, i, 0);
    WAIT(10, mode);
  }

  // Green + white party rhythm
  for (int i = 0; i < 3; i++) {

    setRGB(0, 100, 0);
    WAIT(100, mode);

    setRGB(100, 100, 100);
    WAIT(45, mode);

    setRGB(0, 70, 0);
    WAIT(55, mode);

    allOff();
    WAIT(35, mode);
  }

  // Acceleration
  for (int i = 0; i < 5; i++) {

    setRGB(0, 100, 0);
    WAIT(65 - (i * 7), mode);

    setRGB(100, 100, 100);
    WAIT(30, mode);

    allOff();
    WAIT(25, mode);
  }

  // Party burst
  for (int i = 0; i < 6; i++) {

    setRGB(0, 100, 0);
    WAIT(35, mode);

    setRGB(100, 100, 100);
    WAIT(30, mode);

    setRGB(0, 35, 0);
    WAIT(25, mode);
  }

  // Big white flash
  setRGB(100, 100, 100);
  WAIT(180, mode);

  allOff();
  WAIT(50, mode);

  setRGB(100, 100, 100);
  WAIT(80, mode);

  // Green finale
  for (int i = 0; i <= 100; i += 4) {
    setRGB(0, i, 0);
    WAIT(12, mode);
  }

  WAIT(180, mode);

  for (int i = 100; i >= 0; i -= 3) {
    setRGB(0, i, 0);
    WAIT(15, mode);
  }

  allOff();
  WAIT(250, mode);
}

// -----------------------------------------------------
// MODE 9 — RGB RainbowVegas
// -----------------------------------------------------

void animationJackpot(uint8_t mode) {
  // ===== Wheel acceleration =====
  int d = 120;

  for (uint8_t lap = 0; lap < 3; lap++) {
    for (uint8_t step = 0; step < 6; step++) {
      switch (step) {
        case 0: setRGB(100, 0, 0); break;
        case 1: setRGB(100, 30, 0); break;
        case 2: setRGB(100, 60, 0); break;
        case 3: setRGB(100, 100, 0); break;
        case 4: setRGB(100, 60, 0); break;
        case 5: setRGB(100, 30, 0); break;
      }

      WAIT(d, mode);

      if (d > 20)
        d -= 5;
    }
  }

  // ===== Dramatic stop =====
  setRGB(0, 0, 0);
  WAIT(150, mode);

  // ===== Triple white flash =====
  for (uint8_t flash = 0; flash < 3; flash++) {
    setRGB(100, 100, 100);
    WAIT(80, mode);

    setRGB(0, 0, 0);
    WAIT(80, mode);
  }

  // ===== Gold celebration =====
  for (uint8_t gold = 0; gold < 5; gold++) {
    setRGB(100, 75, 0);
    WAIT(120, mode);

    setRGB(20, 10, 0);
    WAIT(120, mode);
  }

  // ===== Rainbow explosion =====
  for (uint8_t rainbow = 0; rainbow < 4; rainbow++) {
    setRGB(100, 0, 0);
    WAIT(80, mode);

    setRGB(100, 100, 0);
    WAIT(80, mode);

    setRGB(0, 100, 0);
    WAIT(80, mode);

    setRGB(0, 100, 100);
    WAIT(80, mode);

    setRGB(0, 0, 100);
    WAIT(80, mode);

    setRGB(100, 0, 100);
    WAIT(80, mode);
  }

  // ===== RGB glitter =====
  for (uint8_t sparkle = 0; sparkle < 30; sparkle++) {
    setRGB(
      random(20, 101),
      random(20, 101),
      random(20, 101));

    WAIT(random(20, 60), mode);
  }

  // ===== Winner ending =====
  for (uint8_t breath = 0; breath < 3; breath++) {
    for (uint8_t b = 20; b <= 100; b += 5) {
      setRGB(b, (b * 75) / 100, 0);
      WAIT(15, mode);
    }

    for (int b = 100; b >= 20; b -= 5) {
      setRGB(b, (b * 75) / 100, 0);
      WAIT(15, mode);
    }
  }

  setRGB(100, 75, 0);
}

// -----------------------------------------------------
// MODE 10 — RGB RainbowVegas
// -----------------------------------------------------

void animationRainbowVegas(uint8_t mode) {

  for (uint16_t hue = 0; hue < 360; hue++) {

    uint8_t r;
    uint8_t g;
    uint8_t b;

    uint8_t sector = hue / 60;
    uint8_t offset = hue % 60;

    uint8_t ascending = (offset * 100) / 60;
    uint8_t descending = 100 - ascending;

    switch (sector) {

      case 0:  // Red -> Yellow
        r = 100;
        g = ascending;
        b = 0;
        break;

      case 1:  // Yellow -> Green
        r = descending;
        g = 100;
        b = 0;
        break;

      case 2:  // Green -> Cyan
        r = 0;
        g = 100;
        b = ascending;
        break;

      case 3:  // Cyan -> Blue
        r = 0;
        g = descending;
        b = 100;
        break;

      case 4:  // Blue -> Violet
        r = ascending;
        g = 0;
        b = 100;
        break;

      default:  // Violet -> Red
        r = 100;
        g = 0;
        b = descending;
        break;
    }

    setRGB(r, g, b);
    WAIT(8, mode);
  }

  for (uint8_t i = 0; i <= 100; i += 5) {

    // Gradually mix the last rainbow color with white.
    uint8_t r = 100;
    uint8_t g = i;
    uint8_t b = i;

    setRGB(r, g, b);
    WAIT(10, mode);
  }

  setRGB(100, 100, 100);
  WAIT(180, mode);

  for (uint8_t i = 100; i >= 5; i -= 5) {

    // Start from white and restore saturation.
    uint8_t r = 100;
    uint8_t g = i;
    uint8_t b = i;

    setRGB(r, g, b);
    WAIT(10, mode);
  }

  for (int16_t hue = 359; hue >= 0; hue--) {

    uint8_t r;
    uint8_t g;
    uint8_t b;

    uint8_t sector = hue / 60;
    uint8_t offset = hue % 60;

    uint8_t ascending = (offset * 100) / 60;
    uint8_t descending = 100 - ascending;

    switch (sector) {

      case 0:  // Red -> Yellow
        r = 100;
        g = ascending;
        b = 0;
        break;

      case 1:  // Yellow -> Green
        r = descending;
        g = 100;
        b = 0;
        break;

      case 2:  // Green -> Cyan
        r = 0;
        g = 100;
        b = ascending;
        break;

      case 3:  // Cyan -> Blue
        r = 0;
        g = descending;
        b = 100;
        break;

      case 4:  // Blue -> Violet
        r = ascending;
        g = 0;
        b = 100;
        break;

      default:  // Violet -> Red
        r = 100;
        g = 0;
        b = descending;
        break;
    }

    setRGB(r, g, b);
    WAIT(8, mode);
  }

  allOff();
  WAIT(100, mode);
}


// =====================================================
// MODE 11 — RGB MYSTERY
// =====================================================

void animationRGBMystery(uint8_t mode) {

  uint8_t currentR = random(0, 101);
  uint8_t currentG = random(0, 101);
  uint8_t currentB = random(0, 101);

  for (uint8_t scene = 0; scene < 15; scene++) {

    uint8_t targetR;
    uint8_t targetG;
    uint8_t targetB;

    // Most of the time, generate vivid RGB colors.
    // Occasionally allow pastel / white-ish colors.
    if (random(0, 10) < 8) {

      // Pick one dominant RGB channel.
      uint8_t dominant = random(0, 3);

      uint8_t high = random(75, 101);
      uint8_t low1 = random(0, 45);
      uint8_t low2 = random(0, 45);

      if (dominant == 0) {
        targetR = high;
        targetG = low1;
        targetB = low2;
      } else if (dominant == 1) {
        targetR = low1;
        targetG = high;
        targetB = low2;
      } else {
        targetR = low1;
        targetG = low2;
        targetB = high;
      }

    } else {

      // Occasionally generate a mixed / pastel color.
      targetR = random(45, 101);
      targetG = random(45, 101);
      targetB = random(45, 101);
    }

    const uint8_t steps = 40;

    for (uint8_t i = 1; i <= steps; i++) {

      int16_t r =
        (int16_t)currentR + ((int16_t)targetR - currentR) * i / steps;

      int16_t g =
        (int16_t)currentG + ((int16_t)targetG - currentG) * i / steps;

      int16_t b =
        (int16_t)currentB + ((int16_t)targetB - currentB) * i / steps;

      setRGB(
        (uint8_t)r,
        (uint8_t)g,
        (uint8_t)b);

      WAIT(10, mode);
    }

    currentR = targetR;
    currentG = targetG;
    currentB = targetB;

    // Hold the new mysterious color.
    WAIT(random(100, 250), mode);
  }
}


// =====================================================
// Mode 12 - DEMO (all animations)
// =====================================================

void animationDemo(uint8_t mode) {

  // Poker chip denominations — unchanged
  animationChipWhite(mode);
  if (animationMode != mode) return;

  animationChipRed(mode);
  if (animationMode != mode) return;

  animationChipGreen(mode);
  if (animationMode != mode) return;

  animationChipBlue(mode);
  if (animationMode != mode) return;

  animationChipPurple(mode);
  if (animationMode != mode) return;

  animationChipYellow(mode);
  if (animationMode != mode) return;

  animationSlotMachine(mode);
  if (animationMode != mode) return;

  animationAvnetParty(mode);
...

This file has been truncated, please download it to see its full contents.

Credits

Danni Fernandez
5 projects • 32 followers
I'm Danni, a mechatronics engineer who loves building robots, designing PCBs, writing firmware, and bringing crazy ideas to life!

Comments