G1 (SCL)
and G2 (SDA)
./*
* SPDX-FileCopyrightText: 2025 M5Stack Technology CO LTD
*
* SPDX-License-Identifier: MIT
*/
/*
* @Hardwares: M5Stack PortA device + Unit Step16
* @Dependent Library:
* M5Unit-Step16:https://github.com/m5stack/M5Unit-Step16
* @description: When the knob is rotated, only 0-8 is displayed,
* when raw value reaches 9-F, rotation direction is automatically reversed,
* LED brightness follows display value, never zero (minimum 10%),
* RGB color follows the 0-8 pattern
*/
#include <M5Unified.h>
#include <M5UnitStep16.h>
#define I2C_SDA_PIN (2)
#define I2C_SCL_PIN (1)
#define NUM_DIGITS (9)
#define MAX_DIGIT (8)
#define MIN_DIGIT (0)
#define MIN_BRIGHTNESS (10)
#define MAX_BRIGHTNESS (100)
#define BRIGHTNESS_STEP (10)
#define RGB_BRIGHTNESS (70)
#define LED_ALWAYS_ON (0xFF)
UnitStep16 step16;
uint8_t currentDigit = 0;
uint8_t lastRawValue = 0;
bool isFirstRead = true;
const uint8_t digitBrightness[NUM_DIGITS] = {
MIN_BRIGHTNESS, // 0 - 10%
MIN_BRIGHTNESS + BRIGHTNESS_STEP, // 1 - 20%
MIN_BRIGHTNESS + BRIGHTNESS_STEP * 2, // 2 - 30%
MIN_BRIGHTNESS + BRIGHTNESS_STEP * 3, // 3 - 40%
MIN_BRIGHTNESS + BRIGHTNESS_STEP * 4, // 4 - 50%
MIN_BRIGHTNESS + BRIGHTNESS_STEP * 5, // 5 - 60%
MIN_BRIGHTNESS + BRIGHTNESS_STEP * 6, // 6 - 70%
MIN_BRIGHTNESS + BRIGHTNESS_STEP * 7, // 7 - 80%
MIN_BRIGHTNESS + BRIGHTNESS_STEP * 8 // 8 - 90%
};
struct MyRGBColor {
uint8_t r, g, b;
const char* name;
};
const MyRGBColor digitColors[NUM_DIGITS] = {
{0, 0, 128, "Deep Blue"}, // 0 - cold color
{0, 64, 192, "Blue"}, // 1
{0, 128, 255, "Light Blue"}, // 2
{0, 192, 192, "Cyan"}, // 3
{0, 255, 128, "Cyan Green"}, // 4
{128, 255, 0, "Yellow Green"}, // 5
{192, 192, 0, "Yellow"}, // 6
{255, 128, 0, "Orange"}, // 7
{255, 64, 0, "Orange Red"} // 8 - warm color
};
uint8_t mapRawValueToDigit(uint8_t rawValue);
void updateDisplay(uint8_t digit);
uint8_t mapRawValueToDigit(uint8_t rawValue);
void updateDisplay(uint8_t digit);
void handleValueChange(uint8_t oldVal, uint8_t newVal);
void setup()
{
M5.begin();
Serial.begin(115200);
Wire.begin(I2C_SDA_PIN, I2C_SCL_PIN);
while(!step16.begin()){
delay(1000);
Serial.println("M5Unit-Step16 not found!");
}
M5.Display.fillRect(0, 0, 320, 240, WHITE);
M5.Display.setTextColor(BLACK);
M5.Display.setFont(&fonts::FreeMonoBold18pt7b);
M5.Display.setCursor(0, 0);
M5.Display.printf("M5Unit-Step16\n");
step16.setRgbConfig(1);
step16.setRgbBrightness(RGB_BRIGHTNESS);
lastRawValue = step16.getValue();
currentDigit = mapRawValueToDigit(lastRawValue);
updateDisplay(currentDigit);
}
void loop()
{
uint8_t rawValue = step16.getValue();
if (rawValue != lastRawValue && !isFirstRead) {
handleValueChange(lastRawValue, rawValue);
lastRawValue = rawValue;
M5.Display.fillRect(0, 0, 320, 240, WHITE);
M5.Display.setCursor(0, 0);
M5.Display.printf("Raw Value: %d\n", rawValue);
}
if (isFirstRead) isFirstRead = false;
delay(50);
}
/**
* @brief Handle value change
* @param oldVal Old raw value
* @param newVal New raw value
*/
void handleValueChange(uint8_t oldVal, uint8_t newVal)
{
if (newVal >= 9 && newVal <= 15) {
uint8_t currentDirection = step16.getSwitchState();
step16.setSwitchState(currentDirection == 0 ? 1 : 0);
}
uint8_t newDigit = mapRawValueToDigit(newVal);
if (newDigit != currentDigit) {
currentDigit = newDigit;
updateDisplay(currentDigit);
}
}
/**
* @brief Map raw value to digit 0-8
* @param rawValue Raw value (0-15)
* @return Mapped digit (0-8)
*/
uint8_t mapRawValueToDigit(uint8_t rawValue)
{
if (rawValue <= 8) {
return rawValue;
} else {
return 17 - rawValue;
}
}
/**
* @brief Update display
* @param digit Digit to display (0-8)
*/
void updateDisplay(uint8_t digit)
{
if (digit > MAX_DIGIT) return;
step16.setLedBrightness(digitBrightness[digit]);
step16.setRgb(digitColors[digit].r, digitColors[digit].g, digitColors[digit].b);
step16.setLedConfig(LED_ALWAYS_ON);
}
Download Mode: The device needs to enter download mode before programming. This process may vary depending on the main controller. For details, refer to the device programming tutorial list at the bottom of the Arduino IDE Getting Started Tutorial page for specific instructions.
For CoreS3: Press and hold the reset button (about 2 seconds) until the internal green LED lights up, then release. The device is now in download mode and ready for programming.